【问题标题】:How to query objects, each by its ID, from a nested data structure如何从嵌套数据结构中查询对象,每个对象的 ID
【发布时间】:2022-01-11 20:50:53
【问题描述】:

我有一个如下所示的数据结构:

{
  FL: [{ ID: 1, confirmed: true }, { ID: 2, confirmed: false }], 
  TX: [{ ID: 3, confirmed: true }], 
  NY: [{ ID: 4, confirmed: false }, { ID: 5, confirmed: true }],
}

我需要能够遍历此数据中的每个项目并找到 ID 值等于已知 ID 的项目。我不确定如何处理这个问题。

我唯一能想到的是一个 for-in 循环,但我必须在循环对象后映射数组,这样看起来不太干净。

是否有任何干净的方法可以处理如此深度嵌套的数据的迭代?

【问题讨论】:

  • 好的,这些都没有帮助。我的问题是我想不出一种方法来循环一次以读取对象内的数据。我还是新手...
  • Array.prototype.find 帮助人们......好吧......在数组中找到一个对象,Object.values 将一个对象的所有值作为数组返回,而 Array.prototype.flat 有助于展平例如数组数组
  • ... 直接搜索 ID 值为 5 的对象将如下所示... Object.values({/* the object */}).flat().find(({ ID }) => ID === 5)

标签: javascript arrays object search data-structures


【解决方案1】:

Array.prototype.find 帮助人们在数组中查找对象,Object.values 将对象的所有值作为数组返回,而 Array.prototype.flat 帮助扁平化数组数组。

下面的实现还使用Arrow function expressions 作为find 的回调函数以及destructuring_assignment which is applied for unpacking a field from an object passed as a parameter to the callback

function findObjectByID(obj, id) {
  return Object
    .values(obj)
    .flat()
    .find(({ ID }) => ID === id);
}

const sampleData = {
  FL: [{ ID: 1, confirmed: true }, { ID: 2, confirmed: false }], 
  TX: [{ ID: 3, confirmed: true }], 
  NY: [{ ID: 4, confirmed: false }, { ID: 5, confirmed: true }],
};

console.log(
  'findObjectByID(sampleData, 2) ...',
  findObjectByID(sampleData, 2)
);
console.log(
  'findObjectByID(sampleData, 3) ...',
  findObjectByID(sampleData, 3)
);
console.log(
  'findObjectByID(sampleData, 5) ...',
  findObjectByID(sampleData, 5)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

如果 OP 必须从原始数据结构中非常频繁且重复地查询对象,一个更好的方法是将此结构恰好一次转换为平面对象,然后用作基于 ID 的自定义地图或索引数据项(例如,每个项与其原始类别或元键(如'FL''TX''NY')保持关系。

上面提供的示例代码将被重构为下一个类似的代码......

function createIdBasedItemIndex(rawData) {
  return Object
    .entries(rawData)
    .flatMap(([category, itemList]) =>
      itemList.map(item => ({ category, item }))
    )
    .reduce((index, data) =>
      Object.assign(index, { [data.item.ID]: data }), {}
    );
}

const sampleData = {
  FL: [{ ID: 1, confirmed: true }, { ID: 2, confirmed: false }], 
  TX: [{ ID: 3, confirmed: true }], 
  NY: [{ ID: 4, confirmed: false }, { ID: 5, confirmed: true }],
};
const categoryItemIndex = createIdBasedItemIndex(sampleData);

console.log({ sampleData, categoryItemIndex });

console.log('categoryItemIndex[2] ...', categoryItemIndex[2]);
console.log('categoryItemIndex[3] ...', categoryItemIndex[3]);
console.log('categoryItemIndex[5] ...', categoryItemIndex[5]);
.as-console-wrapper { min-height: 100%!important; top: 0; }

【讨论】:

  • @CourtneyJ ... 查看第二种方法,它只将原始数据结构一次转换为易于查找的基于ID 的地图/索引。
【解决方案2】:

这是一个保留密钥并返回匹配项的方法。

let obj = {
  FL: [{ID: 1, confirmed: true},{ID: 2, confirmed: false}], 
  TX: [{ID: 3, confirmed: true}], 
  NY: [{ID: 4, confirmed: false}, {ID: 5, confirmed: true}]
}

const findFromId = (obj, id) => {
  for (let x in obj) {
     if (res = obj[x].find(a => a.ID == id)) return { [x]: res }
  }
  return null;
}

console.log(findFromId(obj, 5))

【讨论】:

    猜你喜欢
    • 2013-04-06
    • 1970-01-01
    • 2021-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多