使用下划线获取每个

时间:2016-09-30 17:06:57

标签: javascript arrays functional-programming underscore.js lodash

从一个对象数组开始,我需要获取所有键的列表以及每个键的所有唯一值。问题是我事先不知道密钥。如果你知道密钥,有很多解决方案,但在这种情况下,每个对象可以有任意数量的密钥,每个密钥都有一个值数组。下面的代码有效,但它非常复杂,必须有一个更简单的解决方案。

Made a working JSBIN here

输入:

[
    {
        key_1: [ attribute_value_1, attribute_value_2, ... ],
        key_2: [ attribute_value_3, attribute_value_4, ... ],
    },
    ...
] 

输出:

[
    {
        label: key_1,
        options: [ attribute_value_1, attribute_value_2, ... ]
    },
    {
        label: key_2,
        options: [ attribute_value_3, attribute_value_4, ... ]
    },
    ...
]

建议的解决方案:

    _.chain(input)
        .map(function (attr) {
            return _.keys(attr).map(function (key) {
                return {
                    key: key,
                    value: attr[key]
                };
            });
        })
        .flatten()
        .groupBy('key')
        .map(function (grouped_values, key) {
            // value = array of { key, value }
            return {
                label: key,
                options: _.chain(grouped_values)
                    .pluck('value')
                    .flatten()
                    .uniq()
                    .value()
            };
        })
        .value();

2 个答案:

答案 0 :(得分:2)

使用lodash - 将_.mergeWith()应用于输入数组,并使用自定义程序功能组合数组并获取唯一值。之后_.map()结果为所需格式:

var input = [
  {
    key_1: [ "attribute_value_1", "attribute_value_2" ],
    key_2: [ "attribute_value_3", "attribute_value_4" ]
  },
  {
    key_1: [ "attribute_value_1", "attribute_value_5" ],
    key_2: [ "attribute_value_2", "attribute_value_3" ],
    key_5: [ "attribute_value_2", "attribute_value_3" ]
  }
];


var params = [{}].concat(input).concat(function (objValue, srcValue) { // create the params to apply to mergeWith
  if (_.isArray(objValue)) {
    return _.union(objValue, srcValue); // merge the arrays, and get the unique values
  }
});

var result = _.map(_.mergeWith.apply(_, params), function(value, key) { // merge all objects in the array, and map the results to required format
  return {
    label: key,
    options: value
    };
  });

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.2/lodash.min.js"></script>

如果你使用ES6,你可以清理丑陋的params数组:

const input = [
  {
    key_1: [ "attribute_value_1", "attribute_value_2" ],
    key_2: [ "attribute_value_3", "attribute_value_4" ]
  },
  {
    key_1: [ "attribute_value_1", "attribute_value_5" ],
    key_2: [ "attribute_value_2", "attribute_value_3" ],
    key_5: [ "attribute_value_2", "attribute_value_3" ]
  }
];

const customizer = (objValue, srcValue) => {
  if (_.isArray(objValue)) {
    return _.union(objValue, srcValue); // merge the arrays, and get the unique values
  }
};

const result = _.map(_.mergeWith({}, ...input, customizer), (value, key) => ({ // merge all objects in the array, and map the results to required format
  label: key,
  options: value
}));

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.2/lodash.min.js"></script>

答案 1 :(得分:2)

如果您愿意,可以在Underscore中写这个,但没有迫切需要这样做。

&#13;
&#13;
const input = [
  {key_1: [1, 2], key_2: [3, 4]},
  {key_3: [5, 6], key_2: [7, 42]}
 ];

var result = [].concat(...input.map(obj => 
  Object.keys(obj).map(key =>
    ({label: key, options: obj[key]})
  )
));

console.log(result);
&#13;
&#13;
&#13;

我不太确定你想要如何统一结果。你的意思是你想在每个数组中运行唯一,例如[ attribute_value_1, attribute_value_2, ... ]