如何从嵌套数据结构中通过 ID 查询对象

How to query objects, each by its ID, from a nested data structure

我的数据结构如下所示:

{
  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 循环,但我必须在遍历对象后映射数组,这样看起来不太干净。

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

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

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))

Array.prototype.find helps one to find an object within an array, and Object.values returns all of an object's values as array, whereas Array.prototype.flat 有助于展平数组数组。

下面的实现也使用了 Arrow function expressions as find's callback function together with a 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; }