如果对象的值与数组匹配,如何过滤对象数组

时间:2019-10-04 09:40:57

标签: javascript

我有以下对象表:

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

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

4 个答案:

答案 0 :(得分: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);

答案 1 :(得分:1)

您可以创建新对象而无需更改原始数据,而仅返回包含所需子字符串的部分。

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; }

答案 2 :(得分:1)

  

我认为我们无法在过滤器中进行过滤。

是的,但是我会使用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);

答案 3 :(得分:0)

您可以这样做

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