2

I have the following object table :

 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"

I would like to filter the table if the value of "message" match with the value of "search"

if search = "sun" the filter should return the following result:

result after filter :

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

here the array only returns the objects having the message value that match with "sun"

I know the filter method but I do not think we can do a filter in a filter.

I also know the method that allows me to match the message :

 message.toLowerCase().includes(search);

but I do not know how to filter the object array, if anyone has an idea?

Greg-A
  • 772
  • 1
  • 19
  • 41
  • 2
    @ponury-kostek this is a little different because I do not filter at the first level but in the second table – Greg-A Oct 04 '19 at 09:50
  • `data.map(item=>({...item, skill=>skill.filter(s=>s.message.includes(search))}).filter(item=>item.skill.length)` – Tiago Coelho Jan 25 '22 at 09:49

4 Answers4

4

You can filter on skill field of each element by search value first then filter elements that still have 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)

Edit for not mutate the original array:

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);
Cuong Le Ngoc
  • 11,595
  • 2
  • 17
  • 39
2

I do not think we can do a filter in a filter.

Yes you can but I would use forEach(). Example below.

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);
Jax-p
  • 7,225
  • 4
  • 28
  • 58
1

You could create new objects without mutating the original data and return only the parts who contain the wanted sub string.

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; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

You can do it this way

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))
})
Mihir Kale
  • 1,028
  • 1
  • 12
  • 20