【问题标题】:How to filter an object array if the value of an object match array [duplicate]如果对象的值匹配数组,如何过滤对象数组[重复]
【发布时间】:2020-02-02 15:18:31
【问题描述】:

我有以下对象表:

 let data = [
   {key:"20-09-2019", skill: [{id: 500, message: "monday"}, {id: 501, message: "tuesday"}]},
   {key:"21-09-2019", skill: [{id: 502, message: "thursday"}, {id: 503, message: "sunday"}]},
   {key:"22-09-2019", skill: [{id: 504, message: "sunday"}]},
]

让搜索 = "太阳"

如果“message”的值与“search”的值匹配,我想过滤表

如果 search = "sun" 过滤器应该返回以下结果:

过滤后的结果:

 data = [
   {key:"21-09-2019", skill: [ {id: 503, message: "sunday"}]},
   {key:"22-09-2019", skill: [{id: 504, message: "sunday"}]},
]

这里的数组只返回消息值与“sun”匹配的对象

我知道过滤方法,但我认为我们不能在过滤器中进行过滤。

我也知道匹配消息的方法:

 message.toLowerCase().includes(search);

但我不知道如何过滤对象数组,如果有人有想法吗?

【问题讨论】:

  • @ponury-kostek 这有点不同,因为我不在第一级过滤,而是在第二个表中过滤

标签: javascript


【解决方案1】:

您可以先通过搜索值对每个元素的skill字段进行过滤,然后过滤仍然有技能的元素。

let search = "sun";
let data = [
   {key:"20-09-2019", skill: [{id: 500, message: "monday"}, {id: 501, message: "tuesday"}]},
   {key:"21-09-2019", skill: [{id: 502, message: "thursday"}, {id: 503, message: "sunday"}]},
   {key:"22-09-2019", skill: [{id: 504, message: "sunday"}]},
];
data.forEach(el => {
  el.skill = el.skill.filter(s => s.message.toLowerCase().includes(search))
});
let result = data.filter(el => el.skill.length);
console.log(result)

编辑不改变原始数组:

let search = "sun";
let data = [
  {key:"20-09-2019", skill: [{id: 500, message: "monday"}, {id: 501, message: "tuesday"}]},
  {key:"21-09-2019", skill: [{id: 502, message: "thursday"}, {id: 503, message: "sunday"}]},
  {key:"22-09-2019", skill: [{id: 504, message: "sunday"}]},
    ];
let result = data.reduce((acc, {skill, ...rest}) => {
   skill = skill.filter(s => s.message.toLowerCase().includes(search));
   if(skill.length) acc.push({skill, ...rest});
   return acc;
}, []);
console.log(result);

【讨论】:

  • 仅供参考,这会改变data。但是,无论出于何种原因,变异 data 可能是 OP 无论如何想要的......
  • @GerardoFurtado 谢谢,但 OP 没有提到需要保留 data
  • 如果您不必突变,最好避免突变。
【解决方案2】:

您可以在不改变原始数据的情况下创建新对象,并且只返回包含所需子字符串的部分。

function filter(array, value) {
    function subFind(array, [key, ...keys]) {
        return keys.length
            ? array
                  .map(o => {
                      var temp = subFind(o[key], keys);
                      return temp.length && Object.assign({}, o, { [key]: temp });
                  })
                  .filter(Boolean)
            : array.filter(o => o[key].includes(value));
    }
    return subFind(array, ['skill', 'message']);
}

let data = [{ key: "20-09-2019", skill: [{ id: 500, message: "monday" }, { id: 501, message: "tuesday" } ]}, { key: "21-09-2019", skill: [{ id: 502, message: "thursday" }, { id: 503, message: "sunday" } ]}, { key: "22-09-2019", skill: [{ id: 504, message: "sunday" }] }];

console.log(filter(data, 'sun'));
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

    【解决方案3】:

    我不认为我们可以在过滤器中做一个过滤器。

    是的,你可以,但我会使用forEach()。下面的例子。

    let data = [{
        key: "20-09-2019",
        skill: [{ id: 500, message: "monday" }, { id: 501, message: "tuesday" }]
      },
      {
        key: "21-09-2019",
        skill: [ { id: 502, message: "thursday" }, { id: 503, message: "sunday" }]
      },
      { 
        key: "22-09-2019", 
        skill: [{ id: 504, message: "sunday" }] 
      }
    ];
    
    let search = "sunday";
    let result = [];
    
    data.forEach(row => {
      let found = row.skill.filter(skill => skill.message === search);
      if (found.length) result.push({ key: row.key, skill: found });
    });
    
    console.log(result);

    【讨论】:

      【解决方案4】:

      你可以这样做

      let data = [
         {key:"20-09-2019", skill: [{id: 500, message: "monday"}, {id: 501, message: "tuesday"}]},
         {key:"21-09-2019", skill: [{id: 502, message: "thursday"}, {id: 503, message: "sunday"}]},
         {key:"22-09-2019", skill: [{id: 504, message: "sunday"}]},
      ];
      
      let search = "sun"
      
      const newItems = data.filter(item => item.skill.filter(sk => sk.message.includes(search)).length);
      newItems.forEach(item => {
        item.skill = item.skill.filter(x => x.message.includes(search))
      })
      

      【讨论】:

      • 这仍然会在输出中保留thursday
      • @MihirKale 决赛桌应该只保留带有“星期日”的消息
      • 查看更新的代码@adiga
      猜你喜欢
      • 1970-01-01
      • 2020-04-13
      • 1970-01-01
      • 2022-09-27
      • 1970-01-01
      • 2021-11-07
      • 2019-10-30
      • 1970-01-01
      • 2021-03-21
      相关资源
      最近更新 更多