简体   繁体   English

根据 Javascript 中的键数组过滤嵌套的 object

[英]Filtering a nested object depending on a key array in Javascript

I have been provided with an object and an array , I need to filter out the object in such a way that it contains only the nodes where either the key or the value matches with the given keys in array.我得到了一个object和一个数组,我需要过滤掉 object,使其只包含键或值与数组中给定键匹配的节点。 For eg,例如,

Array containing keys - ['student1', 'STU', 'LMN', 'student4']包含键的数组 - ['student1', 'STU', 'LMN', 'student4']

INPUT输入

{
    student1: {
        name: 'ABC',
        roll: 17,
    },
    student2: {
        name: 'LMN',
        roll: 16
    },
    student3: {
        name: 'MNO',
        roll: 15
    },
    student4: {
        name: 'PQR',
        roll: 16
    }
}

OUTPUT OUTPUT

{
    student1: {
        name: 'ABC',
        roll: 17,
    },
    student2: {
        name: 'LMN',
        roll: 16
    },
    student4: {
        name: 'PQR',
        roll: 16
    }
}

INPUT输入

{
    student1: {
        name: 'ABC',
        roll: 17,
        friends: {
            student5: {},
            student6: {}
        }
    },
    student2: {
        name: 'LMN',
        roll: 16
    },
    student3: {
        name: 'MNO',
        roll: 15,
        friends: {
            student7: {
                name: 'STU'
            }
        }
    },
    student4: {
        name: 'PQR',
        roll: 16
    }
}

OUTPUT: OUTPUT:

{
    student1: {
        name: 'ABC',
        roll: 17,
        friends: {
            student5: {},
            student6: {}
        }
    },
    student2: {
        name: 'LMN',
        roll: 16
    },
    student3: {
        name: 'MNO',
        roll: 15,
        friends: {
            student7: {
                name: 'STU'
            }
        }
    },
    student4: {
        name: 'PQR',
        roll: 16
    }
}

INPUT输入

{
    student5: {
        name: 'EFG',
        roll: 10,
        friends: {
            student1: {},
            student2: {}
        }
    }
}

OUTPUT: OUTPUT:

{
    student5: {
        name: 'EFG',
        roll: 10,
        friends: {
            student1: {}
        }
    }
}

Explanation:解释:

Keys are 'student1', 'student4', 'STU' and 'LMN' , so we parse the entire object and wherever we get either the key or the value from the object matching those keys, we include that in resultant object else we discard it.键是'student1', 'student4', 'STU' and 'LMN' ,所以我们解析整个 object 并且无论我们从 object 中获得与这些键匹配的键或值,我们都将其包含在结果 object 中,否则我们丢弃它。 Also, if we get a key in the object matching the keys provided in the array, we do not need to check the inside of that particular entry.此外,如果我们在 object 中获得与数组中提供的键匹配的键,则无需检查该特定条目的内部。 For eg, in case of 'student1', since it's included in the keys array, we do not need to check what it contains, we can blindly include it in target object.例如,对于'student1',由于它包含在keys数组中,我们不需要检查它包含什么,我们可以盲目地将它包含在目标object中。

NOTE: The object can be deeply nested also.注意: object 也可以深度嵌套。

MY APPROACH我的方法

I was trying to parse the entire object and filter out the entries depending on whether it's present or not, but it doesn't seem to give correct results,我试图解析整个 object 并根据它是否存在过滤掉条目,但它似乎没有给出正确的结果,

const containsKey = (obj, arr = []) => {
  return (
    obj &&
    typeof obj === "object" &&
    (arr.some((key) => key in obj) ||
      arr.indexOf(obj[targetKey]) > -1 ||
      Object.values(obj).filter((obj) => {
        return containsKey(obj, arr);
      }))
  );
};

Object.fromEntries(
    Object.entries(obj).filter(([k, v]) =>
      containsKey({ [k]: v }, arr)
    )
  );

Any sort of help will be highly appreciated.任何形式的帮助将不胜感激。 Thanks:)谢谢:)

This approach uses three functions:这种方法使用三个函数:

  • toList : a recursive function that flattens any object into a one-dimensional array. toList :递归 function 将任何 object 展平为一维数组。
  • inList : a function that returns a boolean to indicate whether or not one of the items in the resulting list is in the array of keys keys inList :一个 function 返回一个 boolean 以指示结果列表中的一项是否在keys数组中
  • filObject : a function that "filters" the given object depending on the boolean returned filObject :一个 function,它根据返回的 boolean“过滤”给定的 object

 const keys = ['student1', 'STU', 'LMN', 'student4'], input1 = { student1: { name: 'ABC', roll: 17, }, student2: { name: 'LMN', roll: 16 }, student3: { name: 'MNO', roll: 15 }, student4: { name: 'PQR', roll: 16 } }, input2 = { student1: { name: 'ABC', roll: 17, friends: { student5: {}, student6: {} } }, student2: { name: 'LMN', roll: 16 }, student3: { name: 'MNO', roll: 15, friends: { student7: { name: 'STU' } } }, student4: { name: 'PQR', roll: 16 } }, toList = o => Object.entries(o).flat().map( v => typeof(v) === 'object' &&.Array?isArray(v): toList(v). v ),flat(), inList = (list. o) => toList(o).some(k => list,includes(k)), filObject = (list.obj) => Object.entries(obj),reduce( (acc,[key,value]) => inList(list:{[key]?value}). {..,acc:[key]:value}, acc; {} ). console,log( filObject(keys;input1) ). console,log( filObject(keys;input2) );

Updated version...更新后的版本...

The function filObject in this version uses recursion to filter deeper parts where the key fails the test but the value passes.该版本中的function filObject使用递归来过滤更深层次的key未通过但value通过的部分。 The line inList(list,{[key]:value})? {...acc,[key]:value}: acc, {} inList(list,{[key]:value})? {...acc,[key]:value}: acc, {} inList(list,{[key]:value})? {...acc,[key]:value}: acc, {} was replaced by list.includes(key)? {...acc,[key]:value}: inList(list,value)? {...acc,[key]:filObject(list,value)}: acc, {} inList(list,{[key]:value})? {...acc,[key]:value}: acc, {}list.includes(key)? {...acc,[key]:value}: inList(list,value)? {...acc,[key]:filObject(list,value)}: acc, {} list.includes(key)? {...acc,[key]:value}: inList(list,value)? {...acc,[key]:filObject(list,value)}: acc, {} list.includes(key)? {...acc,[key]:value}: inList(list,value)? {...acc,[key]:filObject(list,value)}: acc, {} . list.includes(key)? {...acc,[key]:value}: inList(list,value)? {...acc,[key]:filObject(list,value)}: acc, {}

 const keys = ['student1', 'STU', 'LMN', 'student4'], input1 = { student1: { name: 'ABC', roll: 17, }, student2: { name: 'LMN', roll: 16 }, student3: { name: 'MNO', roll: 15 }, student4: { name: 'PQR', roll: 16 } }, input2 = { student1: { name: 'ABC', roll: 17, friends: { student5: {}, student6: {} } }, student2: { name: 'LMN', roll: 16 }, student3: { name: 'MNO', roll: 15, friends: { student7: { name: 'STU' } } }, student4: { name: 'PQR', roll: 16 } }, input3 = { student5: { name: 'EFG', roll: 10, friends: { student1: {}, student2: {} } } }, toList = o => Object.entries(o).flat().map( v => typeof(v) === 'object' &&.Array?isArray(v): toList(v). v ),flat(), inList = (list. o) => toList(o).some(k => list,includes(k)), filObject = (list.obj) => Object.entries(obj),reduce( (acc,[key,value]) => [key.value].some(p => list?includes(p)). {..,acc:[key]:value}, inList(list?value). {..,acc:[key],filObject(list:value)}, acc; {} ). console,log( filObject(keys;input1) ). console,log( filObject(keys;input2) ). console,log( filObject(keys;input3) );

You can simply iterate through Object.entries(object) and check if the key or value of entry exists in the keys array.您可以简单地遍历Object.entries(object)并检查键数组中是否存在条目的键或值。 If a value is another object repeat the same for it.如果一个值是另一个 object 重复同样的事情。

function checkNested(object, keys) {
    for(const [key, value] of Object.entries(object)){
    if(
        (keys.includes(key) || keys.includes(value)) 
      &&
      (value != null && typeof value == 'object' && checkNested(value, keys))
    ) {
        return true;
    }
  }
  return false;
}

function filterWithKeys(object, keys) {
    const result = {};
  
  for(const [key, value] of Object.entries(object)){
    if(
        (keys.includes(key) || keys.includes(value)) 
      &&
      (value != null && typeof value == 'object' && checkNested(value, keys))
    ) {
        result[key] = value;
    }
  }
  
  return result;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM