javascript根据另一个更大的数组创建具有固定长度的对象数组

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了javascript根据另一个更大的数组创建具有固定长度的对象数组相关的知识,希望对你有一定的参考价值。

给定一个偶数长度的数组:

const items = [
  'this/is/path1',
  'this/is/path2',
  'this/is/path3',
  'this/is/path4',
  'this/is/path5',
  'this/is/path6'
];

我想创建一个具有一定长度objnb的对象数组。根据这个长度,我将上面的items分成块,然后将第一个索引存储在一个新的对象属性path上,以及other1中的以下元素,other2;其他对象块也是如此。

我的解决方案是hacky:

const objnb = 2;
const other1 = true;
const other2 = true;
const outputobjs = items.length / objnb;
const result = items.map((entry, index) => {
  let obj = {};
  console.log({ entry, index })
  if (index % outputobjs === 0) {
    obj.path = entry;
    obj.others = {};
    if (other1) {
      obj.others.two = items[index + 1];
    }
    if (other2) {
      obj.others.three = items[index + 2];
    }

    return obj;
  }

  return obj;
})


console.log('result: ', result)

输出是正确的:

[ { path: 'this/is/path1',
    others: { two: 'this/is/path2', three: 'this/is/path3' } },
  {},
  {},
  { path: 'this/is/path4',
    others: { two: 'this/is/path5', three: 'this/is/path6' } },
  {},
  {} ]

但不幸的是,我得到了空的物品,我不想要。如何以更清洁的方式实现同​​样的目标?

首选结果不包含空对象。

更新

另一个例子是:

const items = [
  'this/is/path1',
  'this/is/path2',
  'this/is/path3',
  'this/is/path4'
];

const objnb = 2;
const other1 = true;
const other2 = false;
const outputobjs = items.length / objnb;
const result = items.map((entry, index) => {
  let obj = {};
  console.log({ entry, index })
  if (index % outputobjs === 0) {
    obj.path = entry;
    obj.others = {};
    if (other1) {
      obj.others.two = items[index + 1];
    }
    if (other2) {
      obj.others.three = items[index + 2];
    }

    return obj;
  }

  return obj;
})


console.log('result: ', result)

结果是:

[ { path: 'this/is/path1', others: { two: 'this/is/path2' } },
  {},
  { path: 'this/is/path3', others: { two: 'this/is/path4' } },
  {} ]

澄清:

新数组中的每个对象都是相似的,例如,它们都将具有path,并且由于我们正在均匀地划分原始数组,因此新对象将具有所有相同的属性。例如,如果有一个two,则新数组中的其余对象都将具有此属性,如果它们应该具有three,则它们都将具有该属性。

新对象将如下所示:

{ path: 'this/is/path1',
    others: { 
       two: 'this/is/path2', 
       three: 'this/is/path3' // optional; if one object has this, others must have it too.
    }
}

所以基本上,通过将原始项目数组划分为特定数字,2,3或4等...我们将其分成较小的数组,新对象path将为chunkedArray[0],如果还有一个项目这个新的chunked数组,然后two将是chunkedArray[1],如果还剩下一个,那么three将是chunkedArray[2]

所以,如果我们除以2,那么我们将:

const chunkedArray1 = [
  'this/is/path1', // path
  'this/is/path2', //others.two
  'this/is/path3' //others.three
];

const chunkedArray2 = [
  'this/is/path4',// path
  'this/is/path5',//others.two
  'this/is/path6'//others.three
];

因此新的物体将有twothree;

但如果我们把它分成3,我们将:

const chunkedArray1 = [
  'this/is/path1',// path
  'this/is/path2'//others.two
];

const chunkedArray2 = [
  'this/is/path3',// path
  'this/is/path4'//others.two
];

const chunkedArray3 = [
  'this/is/path5',// path
  'this/is/path6'//others.two
];

所以我们每个对象只有路径和two

每个新的chunkedArray至少有两个长度,这意味着每个新对象中都存在路径和two

另一个例子:

一个基本的例子是,如果原始数组为3,那么我们不能将它均匀地划分为较小的块,因此:

const items = [
  'this/is/path1', //path
  'this/is/path2',//others.two
  'this/is/path3'//others.three
];

和此相同,如果原始数组是两个长度:

const items = [
  'this/is/path1', //path
  'this/is/path2',//others.two
];
答案

下面是一个使用reduce的解决方案。

const items = [
  'this/is/path1',
  'this/is/path2',
  'this/is/path3',
  'this/is/path4',
  'this/is/path5',
  'this/is/path6'
]

function splitItems(data, chunkSize) {
  if (chunkSize < 2) return data // or the special value you'd like.
  const labels = {
    1: 'one',
    2: 'two',
    3: 'three',
    4: 'four'
    // ... others
  }
  return data.reduce((pre, cur, index) => {
    if (index % chunkSize === 0) {
      /* for old question
      pre.push({
        path: cur,
        others: {}
      })*/
      let newItem = {
        path: cur,
        others: {}
      }
      Array.from(Array(chunkSize-1).keys()).map( itemIndex => {
        newItem.others[labels[(itemIndex+1) % chunkSize + 1]] = '' //or other default valu
      })
      pre.push(newItem)
    }
    else {
      pre[pre.length - 1].others[labels[index % chunkSize + 1]] = items[index]
    }
    return pre
  }, [])
}

console.log('@Test Case 1@', splitItems(items, 2), '@@')
console.log('@Test Case 2@', splitItems(items.slice(0, 2), 2), '@@')
console.log('@Test Case 3@', splitItems(items.slice(0, 4), 2), '@@')
console.log('@Test Case 4@', splitItems(items.slice(0, 5), 3), '@@')

// calc the size first, then exec splitItems
function splitByLength(data, numberOfChunks) {
  let chunkSize = Math.round(data.length/3, 0)
  return splitItems(data, chunkSize)
}
console.log('@Test Case 5@', splitByLength(items.slice(0, 5), 3), '@@')
另一答案

简而言之,您可以循环每个第3项并将其作为对象推送。

const items = [
  'this/is/path1',
  'this/is/path2',
  'this/is/path3',
  'this/is/path4',
  'this/is/path5',
  'this/is/path6'
];
var result = [];
for(var i = 0; i < items.length; i++){
    if(i%3==0){
      result.push({
          path: items[i],
          others: {two: items[i+1] || null, three: items[i+2] || null}
      })
    }
}

console.log(result)
另一答案

使用reduce的另一个解决方案,与@sphinx答案略有不同,虽然非常相似:

const objnb = 3;
const otherKeys = ['two', 'three'];

const items = [
  'this/is/path1',
  'this/is/path2',
  'this/is/path3',
  'this/is/path4',
  'this/is/path5',
  'this/is/path6'
];

const outputobjs = Math.ceil(items.length / objnb);

const ar = items.reduce((memo, item, index) => {
  const mod = index % outputobjs
  if(mod === 0)
    memo.push({path: item, others: {}});
  else if(mod <= otherKeys.length)
    Object.assign(memo[memo.length - 1].others, {[otherKeys[mod -1]]: item});
  return memo;
}, []);

console.log(ar);

以上是关于javascript根据另一个更大的数组创建具有固定长度的对象数组的主要内容,如果未能解决你的问题,请参考以下文章

在 for 循环中删除和添加 numpy 数组行以从更大的 numpy 数组创建动态子数组,

JavaScript 根据使用数组从另一个下拉列表中的选择动态创建选项

如何向 pandas df 添加一个新列,该列从另一个数据帧返回同一组中更大的最小值

(Perl 的)GD 图表 - 绘制数据的限制?

C++ 将两个 int 数组连接成一个更大的数组

Firebase 和 Swift:如何使用另一个数据库来存储更大的文件?