【问题标题】:Filter nested JSON object with multiple arrays and store the filtered objects in an array使用多个数组过滤嵌套的 JSON 对象并将过滤后的对象存储在数组中
【发布时间】:2017-11-01 21:20:59
【问题描述】:

我想过滤与模型数组中的“模型”键匹配的项目数组对象并将它们存储在一个数组中。我的尝试确实成功了,但我对自己的努力不是很满意。有没有更好的方法?

关于如何使用 underscore.js 和 lodash 的任何建议?还是使用本机 javascript 地图和过滤器功能?

JSON 对象

 {
"items": [
  {
    "model": "ooc0d",
    "code": "2x4qr",
    "price": 33
  },
  {
    "model": "ruie9",
    "code": "2f6gi",
    "price": 22
   },
  {
    "model": "aqu0d",
    "code": "2f6gi",
    "price": 21
  },
  {
    "model": "ddebd",
    "code": "2f6gi",
    "price": 25
  },
  {
    "model": "ddebd",
    "code": "2f6gi",
    "price": 29
  }
],
"models": [
  {
    "model": "ruie9",
    "year": 1998
  },
  {
    "model": "ooc0d",
    "year": 1991
  },
  {
    "model": "aqu0d",
    "year": 1994
  },
  {
    "model": "ddebd",
    "year": 1995
  },
  {
    "model": "odq76",
    "year": 1999
  }
]
}

我的解决方案

const { models, items } = jsonData;

const newarray = [];

for(let i = 0; i < models.length; i++) {
   for(let j = 0; j < items.length; j++) {
     if(items[j].model===models[i].model) {

       let obj = {
         ...items[j],
         year: models[i].year
       }
       newarray.push(obj);
    }
   }
 }

【问题讨论】:

  • 在您的代码中,您可以访问id 属性,但您的 JSON 中没有 id 属性的跟踪
  • 糟糕,对不起。刚刚更正
  • @created this benchmark 与我 Umair 和 Pankaj。 Pankaj 获胜 :)

标签: javascript arrays json filter nested


【解决方案1】:

你可以重写

let obj = {
  ...items[j],
  year: models[i].year
}

作为

let obj = Object.assign({}, items[j], { year: models[i].year });

您也可以使用Array.prototype.forEach 代替for 循环,就像这样

models.forEach((m) => {
  items.forEach((i) => {
    if (m.id === i.id) {
      let obj = Object.assign({}, i, { year: m.year });

      newArray.push(obj);
    } 
  })
})

我尽量保持它与您的解决方案相似。

【讨论】:

    【解决方案2】:

    试试这个 sn-p:

    const jsonData = {
      "items": [{
          "model": "ooc0d",
          "code": "2x4qr",
          "price": 33
        },
        {
          "model": "ruie9",
          "code": "2f6gi",
          "price": 22
        },
        {
          "model": "aqu0d",
          "code": "2f6gi",
          "price": 21
        },
        {
          "model": "ddebd",
          "code": "2f6gi",
          "price": 25
        },
        {
          "model": "ddebd",
          "code": "2f6gi",
          "price": 29
        }
      ],
      "models": [{
          "model": "ruie9",
          "year": 1998
        },
        {
          "model": "ooc0d",
          "year": 1991
        },
        {
          "model": "aqu0d",
          "year": 1994
        },
        {
          "model": "ddebd",
          "year": 1995
        },
        {
          "model": "odq76",
          "year": 1999
        }
      ]
    };
    
    var newArray = jsonData.models.reduce(
      (acc, modelData) => {
        let filteredItems = jsonData.items.filter(item => item.model === modelData.model);
        if (filteredItems.length) {
          acc.push(...filteredItems);
        }
        return acc;
      }, [])
    
    console.log(newArray);

    【讨论】:

    • 谢谢 :) 请问[ ] 在reduce 函数的最后做了什么?
    • 嗯,这是一个更清洁的解决方案,但是您在 IMO 详尽无遗的每次迭代中运行 filter
    • @1033 总是受欢迎的。 []acc的初始值,如果省略它是可选的,那么acc的第一个值将是jsonData.models的第一个元素。
    • @Umair 很有趣,但我有意使用过滤器,因为每个模型都与项目有一对多的关系,所以每个模型都可以有多个链接到它的项目,这就是我在每个模型上过滤这些项目的原因。如果您有更好的建议,请随时编辑或添加您的变体。
    • @KarenGrigoryan 我完全理解您对filter 的使用,我并没有说错。请用我喜欢的方法检查我的答案,也请分享你的想法。
    【解决方案3】:

    我会采取稍微不同的方法。我猜你可能会喜欢它。

     const models = [
          {
            "model": "ruie9",
            "year": 1998
          },
          {
            "model": "not-found",
            "year": 1991
          },
          {
            "model": "aqu0d",
            "year": 1994
          },
          {
            "model": "ddebd",
            "year": 1995
          },
          {
            "model": "odq76",
            "year": 1999
          }
        ];
        
        const items = [
          {
            "model": "ooc0d",
            "code": "2x4qr",
            "price": 33
          },
          {
            "model": "ruie9",
            "code": "2f6gi",
            "price": 22
           },
          {
            "model": "aqu0d",
            "code": "2f6gi",
            "price": 21
          },
          {
            "model": "ddebd",
            "code": "2f6gi",
            "price": 25
          },
          {
            "model": "ddebd",
            "code": "2f6gi",
            "price": 29
          }
        ];
        
        
        
        const transformed = models.reduce((res, val) => {
          res[val.model] = val;
          
          return res;
        }, {}); // Transform models into a dictionary.
        
        
        const filtered = items.filter(i => i.model in transformed);
        
        console.log(filtered);

    【讨论】:

    • @1033 很高兴我能帮上忙。
    • 另外,通过使用这种方法,您只需遍历models 列表一次,而不是每次迭代都遍历它。
    • @KarenGrigoryan 这很有趣:)
    【解决方案4】:

    你可以这样做:

    我以为您也想从 models 数组中添加年份。 如果是这样,请查看此实现。这比您之前尝试的O(n*n) 解决方案更有效O(n)。对于大型阵列,O(n*n) 不是首选。

    let items = [{
        "model": "ooc0d",
        "code": "2x4qr",
        "price": 33
      },
      {
        "model": "ruie9",
        "code": "2f6gi",
        "price": 22
      },
      {
        "model": "aqu0d",
        "code": "2f6gi",
        "price": 21
      },
      {
        "model": "ddebd",
        "code": "2f6gi",
        "price": 25
      },
      {
        "model": "ddebd",
        "code": "2f6gi",
        "price": 29
      }
    ];
    
    let models = [
      {
        "model": "ruie9",
        "year": 1998
      },
      {
        "model": "ooc0d",
        "year": 1991
      },
      {
        "model": "aqu0d",
        "year": 1994
      }
    ];
    
    let objModels = models.reduce(function(r,v) {
     r[v.model] = v;
     return r;
    }, {});
    
    let objItems = items.reduce(function(r,v) {
     r[v.model] = v;
     return r;
    }, {});
    
    let ans = [];
    for(let key in objItems) {
       if(key in objModels) {
       let o = objItems[key];
       o.year = objModels[key].year;
        ans.push(o);
        
       }
    }
    
    console.log(ans);

    【讨论】:

    • 太棒了!你能解释一下我的解决方案的复杂性是O(n*n)吗?
    • @Umair 我什么时候说你的是O(n*n)?这是给OP的。但是,您的甚至不是 OP 正在寻找的解决方案。他也希望附上year。查看 OP 尝试的year: models[i].year 行解决方案。
    • @KarenGrigoryan 谢谢!也感谢您设置小提琴!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-08
    • 1970-01-01
    • 2019-11-02
    • 2020-09-17
    • 1970-01-01
    • 2019-08-01
    相关资源
    最近更新 更多