【问题标题】:Search multiple elements by key inside multiple json structures在多个 json 结构中按键搜索多个元素
【发布时间】:2021-12-01 16:57:08
【问题描述】:

我需要获取与items 键匹配的所有数组的值。我正在用 Javascript 制作一个脚本,它需要读取多个 json 文件中多个 items 数组中的对象,但 每个 json 都有不同的结构。示例:

file1.json:

{
   "name":"First file",
   "randomName3874":{
      "items":[
         {
            "name":"item1"
         }
      ]
   },
   "items":[
      {
         "name":"randomItem2"
      }
   ]
}

file2.json

{
   "name":"Another file",
   "randomName00000":{
      "nestedItems":{
         "items":[
            {
               "name":"item87"
            }
         ]
      }
   },
   "stuff":{
      "items":[
         {
            "name":"randomItem35"
         }
      ]
   }
}

期望的结果:

{
   "data":[
      {
         "items":[
            {
               "name":"item1"
            }
         ]
      },
      {
         "items":[
            {
               "name":"randomItem2"
            }
         ]
      },
      {
         "items":[
            {
               "name":"item87"
            }
         ]
      },
      {
         "items":[
            {
               "name":"randomItem35"
            }
         ]
      }
   ]
}

在这两个文件中,我想提取具有键 items 的数组。在上面的示例中,脚本应该找到 4 个数组。正如您在两个文件中看到的那样,每个数组的嵌套方式都不同。我怎样才能使用 Javascript 来做这个?

【问题讨论】:

  • 这能回答你的问题吗? JavaScript recursive search in JSON object
  • 如果file1和file2有固定的结构,你可以写一个简单的循环来合并它们并在单个对象中搜索
  • @deepakchethan 这可能会有所帮助,我会看看

标签: javascript node.js json


【解决方案1】:

这样就可以了:

function omit(key, obj) {
  const { [key]: omitted, ...rest } = obj;
  return rest;
}

function getItems(obj) {
  return (typeof obj === 'object'
    ? 'items' in obj
      ? [{ items: obj.items }].concat(getItems(omit('items', obj)))
      : Object.values(obj).map(v => getItems(v))
    : []
  ).flat()
}
console.log({
  data: [file1, file2].map(o => getItems(o)).flat()
})

看看它的工作原理:

const file1 = {
   "name":"First file",
   "randomName3874":{
      "items":[
         {
            "name":"item1"
         }
      ]
   },
   "items":[
      {
         "name":"randomItem2"
      }
   ]
}
const file2 = {
   "name":"Another file",
   "randomName00000":{
      "nestedItems":{
         "items":[
            {
               "name":"item87"
            }
         ]
      }
   },
   "stuff":{
      "items":[
         {
            "name":"randomItem35"
         }
      ]
   }
}

function omit(key, obj) {
  const { [key]: omitted, ...rest } = obj;
  return rest;
}

function getItems(obj) {
  return (typeof obj === 'object'
    ? 'items' in obj
      ? [{ items: obj.items }].concat(getItems(omit('items', obj)))
      : Object.values(obj).map(v => getItems(v))
    : []
  ).flat()
}
console.log({
  data: [file1, file2].map(o => getItems(o)).flat()
})

让我们更进一步,使其具有通用性(使用对象数组并提取任何键)并将其作为函数提供,您也可以在其他项目中使用它:

function extractKey(objects, key) {
  const omit = (key, obj) => {
    const { [key]: omitted, ...rest } = obj;
    return rest;
  }

  const getValues = (obj) => (typeof obj === 'object'
    ? key in obj
      ? [{ [key]: obj[key] }].concat(getValues(omit(key, obj)))
      : Object.values(obj).map(o => getValues(o))
    : []
  ).flat();
  
  return objects.map(o => getValues(o)).flat()
}

// use: 
extractKey([file1, file2], 'items');

看看它的工作原理:

function extractKey(objects, key) {
  const omit = (key, obj) => {
    const { [key]: omitted, ...rest } = obj;
    return rest;
  }

  const getValues = (obj) => (typeof obj === 'object'
    ? key in obj
      ? [{ [key]: obj[key] }].concat(getValues(omit(key, obj)))
      : Object.values(obj).map(o => getValues(o))
    : []
  ).flat();
  
  return objects.map(o => getValues(o)).flat()
}

// test:

const file1 = {
   "name":"First file",
   "randomName3874":{
      "items":[
         {
            "name":"item1"
         }
      ]
   },
   "items":[
      {
         "name":"randomItem2"
      }
   ]
}
const file2 = {
   "name":"Another file",
   "randomName00000":{
      "nestedItems":{
         "items":[
            {
               "name":"item87"
            }
         ]
      }
   },
   "stuff":{
      "items":[
         {
            "name":"randomItem35"
         }
      ]
   }
}


console.log(
  { data: extractKey([file1, file2], 'items') }
)

【讨论】:

  • 结果中缺少一个对象:/
  • 哦,你是对的。我错过了顶级水平。我的错 :)。我会更新的
  • @Mikel,更新的答案还包括顶级。
  • @MikelGranero,很高兴它有帮助。我将它包装在一个函数中,以便在您想要提取其他东西时可以重复使用它,而不仅仅是“项目”。
【解决方案2】:

应该像树嵌套循环一样循环。

let file1 = {
    "name": "First file",
    "randomName3874": {
        "items": [
            {
                "name": "item1"
            }
        ]
    },
    "items": [
        {
            "name": "randomItem2"
        }
    ]
}

let file2 = {
    "name": "Another file",
    "randomName00000": {
        "nestedItems": {
            "items": [
                {
                    "name": "item87"
                }
            ]
        }
    },
    "stuff": {
        "items": [
            {
                "name": "randomItem35"
            }
        ]
    }
}

let itemsValues = [];
let desiredKey = 'items'

let loop = (value) => {
    if (Array.isArray(value)) { 
        value.forEach(loop);
    } else if (typeof value === 'object' && value !== null) {
        Object.entries(value).forEach(([key, val]) => (key === desiredKey) ? itemsValues.push({ [desiredKey]:  val }) : loop(val));
    }
}

loop(file1);
loop(file2);

console.log(itemsValues);

【讨论】:

    【解决方案3】:

    这应该可行:

    function getIdInObjects(id, objects, output = { data: [] }) {
      if (id in objects) output.data.push({[id]: objects[id]});
    
      for (const key in objects) {
        if (typeof(objects[key]) === 'object') getIdInObjects(id, objects[key], output);
      }
      return output;                                                                                                                                                                                                                         
    }
    console.log('items', [object1, object2])
    

    【讨论】:

      猜你喜欢
      • 2023-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-24
      • 2013-05-04
      • 2020-07-27
      • 2021-11-13
      • 1970-01-01
      相关资源
      最近更新 更多