映射数组以连接共享属性,javascript

时间:2017-12-12 02:51:41

标签: javascript lodash

我有一个如下所示的数据集:

[
[a, 10],
[b, 20],
[c, 30],
[d, 40],
["err", NaN],
[a, "foo"],
[b, "foo2"],
[c, "foo3"],
[f, "foo4"]
]

我想要映射每个数组的第一个对象,如果它重复设置为这样,如果之前没有显示填充空值:

[a, 10, "foo"],
[b, 20, "foo2"],
[c, 30, "foo3"],
[d, 40, null ],
[f, null, "foo4"]

我使用的是lodash,但我是noob。 任何想法如何接近真的很感激。

2 个答案:

答案 0 :(得分:0)

您可以使用Array.prototype.reduce执行此操作。您需要获取数组的第一个元素,如果是第一次遇到它,则将其存储在索引及其在结果数组中的位置。然后将数组的副本添加到结果数组中。

如果您之前看过索引,只需将值附加到结果数组即可。 E.g。

// First elements are changed to strings for simplicity
var data = [
  ['a', 10],
  ['b', 20],
  ['c', 30],
  ['d', 40],
  ['err', NaN],
  ['a', "foo"],
  ['b', "foo2"],
  ['c', "foo3"],
  ['f', "foo4"]
];

var result = data.reduce(function(acc, arr){

  // Use first element of array as a key. If not seen before, add
  // to index object with its index in the data array.
  // Then append a copy of the data array.
  if (!acc.index.hasOwnProperty(arr[0])) {
    acc.index[arr[0]] = acc.data.length;
    acc.data.push(arr.slice());
    
  // Otherwise, just append the value to appropriate array in data  
  } else {
    acc.data[acc.index[arr[0]]].push(arr[1]);
  }
  
  return acc;

// Required output is in data property
}, {index:{}, data:[]}).data;

console.log(result);

为简单起见,我已将变量更改为字符串。只需确保每个变量的值在字符串化时都是唯一的,并且适合作为对象属性,否则您需要使用Map

这可能会更加简洁,存在混淆的风险。

答案 1 :(得分:0)

使用lodash

启动一个lodash的链。使用_.groupBy()通过第一个索引将数组收集到一个组中。使用_.map()迭代组,初始化包含键(0索引)和null的项目。迭代组项,并获取数组的第二个值。通过检查数字是否为数字(_.isNumber)将值插入正确的位置:



var arr = [["a",10],["b",20],["c",30],["d",40],["err",null],["a","foo"],["b","foo2"],["c","foo3"],["f","foo4"]];

var result = _(arr) // start a chain
  .groupBy('0') // group by index 0
  .map(function(group, key) { // map the groups
    var item = [key, null, null]; // init an item
    
    // iterate the group
    group.forEach(function(s) {
      item[_.isNumber(s[1]) ? 1 : 2] = s[1]; // add the number or the string to the right place
    });
    
    return item;
  })
  .value(); // get the chain value
  
console.log(result);

<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
&#13;
&#13;
&#13;

使用ES6

Reduce数组到ES6 Map。对于每个项目,检查它是否存在于地图中,如果不存在,则添加if if not init包含密钥(0索引)和null s的项目。如果值为数字,则将其放在索引1中;如果不是,则将值放在2。将地图values iteratorspread恢复为数组:

&#13;
&#13;
const arr = [["a",10],["b",20],["c",30],["d",40],["err",null],["a","foo"],["b","foo2"],["c","foo3"],["f","foo4"]];

const result = [...arr.reduce((m, [key, value]) => {
  // if item doesn't exist in the Map, create a new item
  m.has(key) || m.set(key, [key, null, null]);
  
  // get the item from the map, and set the new value in the right place
  m.get(key)[typeof value === 'number' ? 1 : 2] = value;
  
  return m;
}, new Map()).values()]; // get the Map's value iterator and spread to an array
  
console.log(result);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
&#13;
&#13;
&#13;