获取对象数组中值为数组的所有键

3
我尝试将值为数组的对象中所有键写入一个新数组,不包含重复项。在JavaScript中,没有像lodash或underscore这样的库,有什么最好的方法。我认为我的解决方案肯定是可以改进的。单个对象及其键是可变的,并且不总是相同的。欢迎提出建议。
示例的预期输出应为: [ "stuff", "type", "misc", "something" ]

const items = [{
    name: "Joe",
    occupied: "no",
    mobile: "yes",
    treatment: "no",
    date: "29-03-2020",
    age: "15",
    stuff: ["A", "B", "C"],
    type: ["1", "2"]
  },
  {
    name: "Jack",
    occupied: "yes",
    mobile: "no",
    treatment: "no",
    date: "02-03-2020",
    age: "20",
    stuff: ["A", "B", "C", "D", "E"],
    type: ["8", "6"],
    misc: ["otherStuff", "someStuff"]
  },
  {
    name: "Jane",
    occupied: "no",
    mobile: "yes",
    treatment: "yes",
    date: "15-02-2020",
    age: "28",
    stuff: ["C", "D", "E"],
    type: ["4", "7"],
    something: ["xxx", "ccc"]
  }
];


function getKeysWithArrayValues(myArray) {
  const result = [];
  myArray.forEach(item => Object.entries(item).forEach(itm => itm.filter(Array.isArray).forEach(x => result.push(itm.slice(0, 1)))));
  return flatArray(result)
};

function flatArray(array) {
  return array.reduce((acc, val) => Array.isArray(val) ? acc.concat(flatArray(val)) : acc.concat(val), []);
};
const ttt = getKeysWithArrayValues(items);
const flat = Array.from(new Set(ttt))
console.log(flat);


1
please add your solution. - Nina Scholz
1
@nina 编辑了可运行的代码片段。 - Rambone
5个回答

2

这是我的解决方案,希望能有所帮助。算法非常清晰,我想不需要太多的解释。我们只需使用reduce方法遍历数组,并最终构建一个新数组,其中仅包含符合我们要求的键。

Array.isArray(rec [key])检查值是否为数组。

acc.indexOf(key) < 0 检查该键是否已在之前的步骤中被包含在结果数组中。

const arr_ = items
  .reduce((acc, rec) => {
    return [...acc, ...Object.keys(rec).filter(key => Array.isArray(rec[key]) && acc.indexOf(key) < 0)]
  }, [])

1
使用 flatMap 遍历每个对象的键,并返回一个经过过滤的键数组,条件是该键对应的值是一个数组:

const items=[{name:"Joe",occupied:"no",mobile:"yes",treatment:"no",date:"29-03-2020",age:"15",stuff:["A","B","C"],type:["1","2"]},{name:"Jack",occupied:"yes",mobile:"no",treatment:"no",date:"02-03-2020",age:"20",stuff:["A","B","C","D","E"],type:["8","6"],misc:["otherStuff","someStuff"]},{name:"Jane",occupied:"no",mobile:"yes",treatment:"yes",date:"15-02-2020",age:"28",stuff:["C","D","E"],type:["4","7"],something:["xxx","ccc"]}];

const keysWithArrays = new Set(
  items.flatMap(
    item => Object.keys(item).filter(key => Array.isArray(item[key]))
  )
);
console.log([...keysWithArrays]);


flatMap还是实验性的吗? - Rambone
1
它的语法和操作已经标准化,并且在所有主要浏览器中都得到了本地支持。它肯定会成为官方语言的一部分,我不会称其为实验性的。为了与旧版浏览器兼容,您可以使用polyfill。 - CertainPerformance
我很喜欢它,因为它非常简洁;) - Rambone

1
你可以使用 Set 来获取对象的唯一键。

const
    items = [{ name: "Joe", occupied: "no", mobile: "yes", treatment: "no", date: "29-03-2020", age: "15", stuff: ["A", "B", "C"], type: ["1", "2"] }, { name: "Jack", occupied: "yes", mobile: "no", treatment: "no", date: "02-03-2020", age: "20", stuff: ["A", "B", "C", "D", "E"], type: ["8", "6"], misc: ["otherStuff", "someStuff"] }, { name: "Jane", occupied: "no", mobile: "yes", treatment: "yes", date: "15-02-2020", age: "28", stuff: ["C", "D", "E"], type: ["4", "7"], something: ["xxx", "ccc"] }],
    keys = Array.from(
         items.reduce(
             (s, o) => Object
                  .keys(o)
                  .reduce((t, k) => Array.isArray(o[k]) ? t.add(k) : t, s),
             new Set
        )
    );

console.log(keys);


1
你可以使用 set 和 Array.isArray() 来检查值是否为数组。

let mySet = new Set();    const items = [{name: "Joe",occupied: "no",mobile: "yes",treatment: "no",date: "29-03-2020",age: "15",stuff: ["A", "B", "C"],type: ["1", "2"]},{name: "Jack",occupied: "yes",mobile: "no",treatment: "no",date: "02-03-2020",age: "20",stuff: ["A", "B", "C", "D", "E"],type: ["8", "6"],misc: ["otherStuff", "someStuff"]
}, {name: "Jane",occupied: "no",mobile: "yes",treatment: "yes",date: "15-02-2020",age: "28",stuff: ["C", "D", "E"],type: ["4", "7"],something: ["xxx", "ccc"]}];

items.forEach((obj)=> Object.keys(obj).forEach( prop=>{if(Array.isArray(obj[prop])) 
mySet.add(prop)})); console.log(Array.from(mySet));
.as-console-wrapper { max-height: 100% !important; top: 0; }


1

使用 Object.fromEntriesflatMapfilter 的另一种方式。

const items = [
  {
    name: "Joe",
    occupied: "no",
    mobile: "yes",
    treatment: "no",
    date: "29-03-2020",
    age: "15",
    stuff: ["A", "B", "C"],
    type: ["1", "2"]
  },
  {
    name: "Jack",
    occupied: "yes",
    mobile: "no",
    treatment: "no",
    date: "02-03-2020",
    age: "20",
    stuff: ["A", "B", "C", "D", "E"],
    type: ["8", "6"],
    misc: ["otherStuff", "someStuff"]
  },
  {
    name: "Jane",
    occupied: "no",
    mobile: "yes",
    treatment: "yes",
    date: "15-02-2020",
    age: "28",
    stuff: ["C", "D", "E"],
    type: ["4", "7"],
    something: ["xxx", "ccc"]
  }
];

const keys = Object.keys(
  Object.fromEntries(
    items.flatMap(item =>
      Object.entries(item).filter(([, value]) => Array.isArray(value))
    )
  )
);

console.log(keys);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接