【问题标题】:Get all keys in array of objects whose values are arrays获取值为数组的对象数组中的所有键
【发布时间】:2020-03-29 21:03:48
【问题描述】:

我尝试将值是数组的对象数组中的所有键写入新数组。没有重复。 什么是 javascript 中最好的方法,没有像 lodash 或 underscore 这样的库。我认为我的解决方案绝对是可以改进的。单个对象及其键是可变的,并不总是相同的。 欢迎提出建议。

我的示例的预期输出应该是: [ “东西”, “类型”, “杂项”, “某物” ]

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

【问题讨论】:

  • 请添加您的解决方案。
  • @nina 将代码编辑为可运行的 sn-p

标签: javascript arrays json object


【解决方案1】:

这是我的解决方案,希望对您有所帮助。算法很清楚,我想没有必要解释太多。我们只是使用 reduce 方法遍历一个数组,最后构建一个只包含符合我们要求的键的新数组。

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

acc.indexOf(key)

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

【讨论】:

    【解决方案2】:

    您可以使用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);

    【讨论】:

      【解决方案3】:

      使用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 还不是实验性的吗?
      • 它的语法和操作已经标准化,是supported natively in all major browsers。它肯定会成为官方语言的一部分,我不会称之为实验性的。为了与旧浏览器兼容,您可以使用 polyfill。
      • 我最喜欢它,因为它简洁;)
      【解决方案4】:

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

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

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          猜你喜欢
          • 2020-11-11
          • 1970-01-01
          • 2014-10-17
          • 2021-03-17
          • 2022-08-03
          • 2022-11-27
          • 2018-11-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多