使用 LoDash 或类似方法规范化/扁平化 JS 数组

Normalize/Flatten a JS array using LoDash or similar?

本文关键字:扁平化 JS 数组 规范化 方法 LoDash 使用      更新时间:2023-09-26

我需要能够规范化一个javascript对象或扁平化它,我希望能够用lodash做一些事情,但我不知所措。我尝试编写自己的转换器,但它似乎过于复杂,我认为 lodash 能够做这样的事情。

正在放置我拥有的原始数组,它有 3 个带有子数组的项目。(见下文)

这就是我所期望的(创建我的新对象),所以所有内容都被展平并添加到"名称"中(请参阅下面的testProduct1和testProduct2),如果没有颜色,位置可用,则名称只是原始名称(请参阅下面的testProduct3)。

{
   name: ‘testProduct1 RED NewYork’
},
{
   name: ‘testProduct1 RED London’
},
{
   name: ‘testProduct1 YELLOW NewYork’
},
{
   name: ‘testProduct1 YELLOW London’
},
{
   name: ‘testProduct2 WHITE NewYork’
},
{
   name: ‘testProduct2 WHITE London’
},
{
   name: ‘testProduct3’
}

这是原始数组的示例

{
    name: ‘testProduct1’,
    colors: [
       ‘RED’,
       ‘YELLOW’
    ],
    locations: [
       ‘New York’,
       ‘London’
    ]
},
{
    name: ‘testProduct2’,
    colors: [
       ‘WHITE’
    ],
    locations: [
       ‘New York’,
       ‘London’
    ]
},
{
    name: ‘testProduct3’,
}

这是普通 Javascript 中的解决方案。

var data = [{ name: 'testProduct1', colors: ['RED', 'YELLOW'], locations: ['New York', 'London'] }, { name: 'testProduct2', colors: ['WHITE'], locations: ['New York', 'London'] }, { name: 'testProduct3', }],
    flat = function (array) {
        var order = ['colors', 'locations'],
        r = [];
        array.forEach(function (a) {
            function getParts(parts) {
                if (parts.length >= order.length) {
                    parts.unshift(a.name);
                    r.push({ name: parts.filter(Boolean).join(' ') });
                    return;
                }
                (a[order[parts.length]] || ['']).forEach(function (b) {
                    getParts(parts.concat(b));
                });
            }
            getParts([]);
        });
        return r;
    }(data);
document.write('<pre>' + JSON.stringify(flat, 0, 4) + '</pre>');

我想你想要一个map

list.map((element) => {
    return {
        name: [element.name].concat(element.colors, element.locations).join(' ')
    };
});
var resultArr = inArr.reduce((initArr, cur) =>
  {
    if (cur.colors && cur.locations)
    {
      cur.colors.forEach(col => 
      cur.locations.forEach(loc =>
        initArr.push({ name: cur.name + ' ' + col + ' ' + loc })));
    }  
    else
    {
      initArr.push({ name: cur.name });
    }
    return initArr;
  }, [] /* Passed as initArr */);

更简洁

var resultArr = inArr.reduce((initArr, cur) =>
  {
    for (let col of cur.colors || ['']) 
      for (let loc of cur.locations || [''])
        initArr.push({ name: (cur.name + ' ' + col + ' ' + loc).trim() });
    return initArr;
  }, [] /* Passed as initArr */);

编写一组基本循环可能更容易:

var result = [];
for (let i = 0; i < arr.length; i++) {
  let colors = arr[i].colors || [];
  for (let j = 0; j < colors.length; j++) {
    let locations = arr[i].locations || [];
    for (let k = 0; k < locations.length; k++) {
      result.push({name: arr[i].name + ' ' + colors[j] + ' ' + locations[k]]});
    ]
  }
}

如果你真的想用函数式风格写这个,那么一个想法是:

[].concat(...arr.map(
  elt => (elt.colors || []).map(
    color => (elt.locations || []).map(
      location => ({name: elt.name + ' ' + color + ' ' + location})))))