Javascript 从深度嵌套的数组对象结构中提取值

问题描述 投票:0回答:1

我正在尝试从后端数据中提取特定字段以准备表格的主体。传入的数据具有以下结构:

[
{
_id: "63056cee252b83f4bc8f97e9",
goals: [
{ title: "Cook" },
{ title: "Budget" }
],
visitEnd: "2022-08-18T00:30:00.000Z",
visitStart: "2022-08-17T21:30:00.000Z",
},
{
_id: "63223586798c6b2658a0d576",
goals: [
{ title: "Cook" },
{ title: "Budget" },
{ title: "Clean" }
],
visitEnd: "2022-09-13T00:30:00.000Z",
visitStart: "2022-09-12T22:00:00.000Z"
},
{
_id: "63542ecfca5bd097a0d9acaf",
goals: [
{ title: "Cook" },
{ title: "Clean" }
],
visitEnd: "2022-10-12T19:00:11.000Z",
visitStart: "2022-10-12T17:00:00.000Z",
}]

由于表格标题是按月/年划分的,因此我使用 lodash 按月对它们进行分组,这让我来到这里:

Object { 7: (2) […], 8: (2) […], 9: (2) […] }
​
7: Array [ {…}, {…} ]
​​
0: Object { user: "62410a1dcaac9a3d0528de7a", location: "Firm Office in LA", visitStart: "2022-08-17T21:30:00.000Z", … }
​​
1: Object { user: "62410a1dcaac9a3d0528de7a", location: "place", visitStart: "2022-08-11T21:00:57.000Z", … }
​​
length: 2
​​
<prototype>: Array []
​
8: Array [ {…}, {…} ]
​​
0: Object { user: "62410a1dcaac9a3d0528de7a", location: "Home", visitStart: "2022-09-12T22:00:00.000Z", … }
​​
1: Object { user: "62410a1dcaac9a3d0528de7a", location: "place", visitStart: "2022-09-21T21:00:00.000Z", … }
​​
length: 2
​​
<prototype>: Array []
​
9: Array [ {…}, {…} ]
​​
0: Object { user: "62410a1dcaac9a3d0528de7a", location: "Home", visitStart: "2022-10-12T17:00:00.000Z", … }
​​
1: Object { user: "62410a1dcaac9a3d0528de7a", location: "place", visitStart: "2022-10-21T21:00:00.000Z", … }
​​
length: 2

但是现在我被卡住了,因为我想隔离目标数组的字段,它在对象中,在每个月的数组中,它包含在一个对象中。我试过玩弄 Object.keys 和地图,然后从这里开始:https://dev.to/flexdinesh/accessing-nested-objects-in-javascript--9m4 came access a function to get deeply nested项目。但我还是把它搞砸了,我的头在旋转,试图弄明白它。我查看了 lodash 的映射和属性,但不确定如何实现给定的嵌套层,我正尝试在 groupBy 对象中的动态命名数组上工作。这是我所在的位置,但我收到错误 i.map is not a function

const sort = groupBy(visits, ({visitEnd})=> new Date(visitEnd).getMonth());
   console.log("sort 1: ", sort)
   const stage = Object.keys(sort).map((i) => {
      { i.map((el) => getNestedObject(el, ['goals', 'title'])) }
      })
   console.log("sort 2: ", stage)

我的 javascript 知识很糟糕,这无济于事……

javascript lodash
1个回答
1
投票

你得到的错误,

i.map
is not a function,意味着变量
i
不是数组。根据您在帖子中提供的数据
i
是一个对象。

使用

Object.entries()
Object.keys()
迭代排序的月/年数据的结果。

要获得每月的独特目标列表,输出如下:

{
    7: ["Cook", "Spend", "Clean"],
    8: ["Cook", "Budget", "Clean"],
    9: ["Cook", "Budget", "Scrub", "Fold", "Rest", "Wash"]
}

const dataSortedByMoYrObj = {
  7: [{
      user: "62410a1dcaac9a3d0528de7a",
      location: "Firm Office in LA",
      visitStart: "2022-08-17T21:30:00.000Z",
      goals: [{
          title: ""
        },
        {
          title: "Spend"
        },
        {
          title: "Clean"
        }
      ]
    },
    {
      user: "62410a1dcaac9a3d0528de7a",
      location: "place",
      visitStart: "2022-08-11T21:00:57.000Z",
      goals: [{
          title: "Cook"
        },
        {
          title: undefined
        }
      ]
    }
  ],
  8: [{
      user: "62410a1dcaac9a3d0528de7a",
      location: "Home",
      visitStart: "2022-09-12T22:00:00.000Z",
      goals: [{
          title: "Cook"
        },
        {
          title: "Budget"
        },
        {
          title: null
        }
      ]
    },
    {
      user: "62410a1dcaac9a3d0528de7a",
      location: "place",
      visitStart: "2022-09-21T21:00:00.000Z"
    }
  ],
  9: [{
      user: "62410a1dcaac9a3d0528de7a",
      location: "Home",
      visitStart: "2022-10-12T17:00:00.000Z",
      goals: [{
          title: "Cook"
        },
        {
          title: "Budget"
        },
        {
          title: "Scrub"
        }
      ]
    },
    {
      user: "62410a1dcaac9a3d0528de7a",
      location: "place",
      visitStart: "2022-10-21T21:00:00.000Z",
      goals: [{
          title: "Fold"
        },
        {
          title: "Rest"
        },
        {
          title: "Wash"
        }
      ]
    }
  ]
};

// 'const getNestedObject' code sourced from:
// https://dev.to/flexdinesh/accessing-nested-objects-in-javascript--9m4
const getNestedObject = (nestedObj, pathArr) => {
  return pathArr.reduce((obj, key) =>
    (obj && obj[key] !== 'undefined') ? obj[key] : undefined, nestedObj);
}

const goalsByMonthYearObj = {};
Object.entries(dataSortedByMoYrObj).forEach(([month, users]) => {
  // 'month' represents the key.
  // 'users' is an array of 'user' objects listed for each month.
  let goalsByMonth = [];
  users.forEach(user => {
    const goalsProp = getNestedObject(user, ['goals']);
    // Check if the 'goals' property is a valid.
    // If 'goals' property is 'null' or 'undefined',
    // '!Array.isArray(null)' returns 'true'.
    if (!Array.isArray(goalsProp)) {
      return;
    }
    // Convert list of goal objects (e.g. '{title: Budget}')
    // to an array using 'goalsProp.map()'.
    // Use the 'filter()' method first to remove empty strings
    // 'null' and 'undefined' values in the 'title' property.
    // https://stackoverflow.com/questions/24806772/how-to-skip-over-an-element-in-map
    const goalsArr = goalsProp.filter(goal => goal.title).map(goal => goal.title);
    // Concatenate goals array to the existing goals-by-month array.
    goalsByMonth = goalsByMonth.concat(goalsArr);
  });
  // Sort array of goals alphabetically
  // https://stackoverflow.com/a/45544166
  goalsByMonth.sort((a, b) => a.localeCompare(b));
  // Add array of unique goals for each month
  // https://stackoverflow.com/questions/1960473/get-all-unique-values-in-a-javascript-array-remove-duplicates
  goalsByMonthYearObj[month] = [...new Set(goalsByMonth)];
});
console.log(goalsByMonthYearObj);

(原始代码不像上面的片段那么简洁。)

const goalsByMonthYearObj = {};

// Reference to 'Object.entries()' at:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries
for (const [key, value] of Object.entries(dataSortedByMoYrObj)) {
    // 'key' represents a month index.
    // 'value' contains an array of objects listed for each month index.
    //console.log(`${key}: ${value}`);

    const goalsByMonth = [];

    value.forEach(item => {
        // The 'goals' property is only one level deep so
        // it's not necessary to use the 'getNestedObject()'
        // function. 
        // For example: const goalsProp = item.goals;
        // The function is useful for more deeply
        // embedded properties. 
        const goalsProp = getNestedObject(item, ['goals']);

        if (!Array.isArray(goalsProp)) { return; }

        goalsProp.forEach(goal => {
            if (!goal.title) { return; }
            goalsByMonth.push(goal.title);
        });
    });

    // https://stackoverflow.com/questions/1960473/get-all-unique-values-in-a-javascript-array-remove-duplicates
    const uniqueGoals = [...new Set(goalsByMonth)];

    goalsByMonthYearObj[key] = uniqueGoals;
}

console.log(goalsByMonthYearObj);
© www.soinside.com 2019 - 2024. All rights reserved.