如何基于键对数组进行分组,以及如何使用分组数组作为值创建动态对象?

时间:2019-02-02 17:54:34

标签: javascript arrays multidimensional-array

我有多个items,其中一些具有相同的title。我想创建一个多维数组,将title作为第一个键并将一个唯一的数字作为第二个键。因此可以按itemstitle进行分类。

示例:

itemArray['title1'][0] = item1

itemArray['title1'][1] = item2

itemArray['title2'][0] = item3

我的示例正在使用此代码,但我认为这太复杂了,我希望JavaScript还有另一种方法。

let itemArray = {}
items.forEach(item => {
    let title = item['title']

    if (itemArray[title] == null) {
      itemArray[title] = {}
    }
    let index = Object.keys(itemArray[title]).length
    itemArray[title][index] = item
  },
)

输入:

[ RowDataPacket {
    uid: 1,
    title: 'booktitle',
    description: 'description' },
  RowDataPacket {
    uid: 2,
    title: 'booktitle',
    description: 'description 2' },
  RowDataPacket {
    uid: 1,
    title: 'booktitle 2',
    description: 'description' } ]

预期的输出(由于它是sql查询的结果,因此该项目是RowDataPacket):

{ 'booktitle':
    { '0':
      RowDataPacket {
        uid: 1,
        title: 'booktitle',
        description: 'description'  } },
    { '1':
      RowDataPacket {
        uid: 2,
        title: 'booktitle',
        description: 'description 2'  } },
  'booktitle 2':
    { '0':
      RowDataPacket {
        uid: 1,
        title: 'booktitle 2',
        description: 'description'  } }
}

使用PHP很容易,它的工作方式如下:

$itemArray = array();
foreach ($items as $key => $item) {
    $itemArray[$item['title']][] = $item;
}

谢谢!

3 个答案:

答案 0 :(得分:3)

您有正确的主意。您创建的nuxtServerInit不是多维数组。这是一个对象,每个itemArray作为键,一个title的数组与它们的值共享相同的items。您可以这样简化您的title

forEach

检查var items = [{ uid: 1, title: 'booktitle', description: 'description' }, { uid: 2, title: 'booktitle', description: 'description 2' }, { uid: 1, title: 'booktitle 2', description: 'description' }] let itemArray = {} items.forEach(item => { itemArray[item.title] = itemArray[item.title] || []; itemArray[item.title].push(item) }) console.log(itemArray)是否已将itemArray作为密钥。如果是,请使用它。否则,将其指向空数组title。然后只需push当前[]到该属性。

借助reduce,您甚至可以将其简化为:

item

答案 1 :(得分:3)

您可以通过采用默认数组并推入项目来缩小数组。

var items = [{ title: 'title1' }, { title: 'title1' }, { title: 'title2' }],
    result = items.reduce((r, item) => {
        (r[item.title] = r[item.title] || []).push(item);
        return r;
    }, {});
    
console.log(result);

答案 2 :(得分:0)

  

预期产量

     

{ 'booktitle': { '0': RowDataPacket { uid: 1, title: 'booktitle', description: 'description' } }, { '1': RowDataPacket { uid: 2, title: 'booktitle', description: 'description 2' } }, 'booktitle 2': { '0': RowDataPacket { uid: 1, title: 'booktitle 2', description: 'description' } } }

这是一个坏习惯。不要在对象上使用枚举属性。您会看到它们多么繁琐。与PHP不同,JS没有关联数组。因此使用对象是正确的选择。但是对于索引数组,您应该在JS中使用数组,而不是对象。

var data = [{
    uid: 1,
    title: 'booktitle',
    description: 'description'
  },
  {
    uid: 2,
    title: 'booktitle',
    description: 'description 2'
  },
  {
    uid: 1,
    title: 'booktitle 2',
    description: 'description'
  }
];

const booksByTitle = {};
for (const item of data) {
  const {
    title
  } = item;
  if (!(title in booksByTitle)) booksByTitle[title] = [];
  booksByTitle[title].push(item);
}
console.log(booksByTitle);
.as-console-wrapper{top:0;max-height:100%!important}

但也有很多也是JS,提供框架的一些groupBy方法,像这样快速实现:

var data = [{
    uid: 1,
    title: 'booktitle',
    description: 'description'
  },
  {
    uid: 2,
    title: 'booktitle',
    description: 'description 2'
  },
  {
    uid: 1,
    title: 'booktitle 2',
    description: 'description'
  }
];

function groupBy(iterable, keyOrFn) {
  const fn = typeof keyOrFn === "function" ?
    keyOrFn :
    (item) => item == null ? undefined : item[keyOrFn];

  var result = Object.create(null);
  for (const item of iterable) {
    const key = fn(item);
    if (key in result) {
      result[key].push(item);
    } else {
      result[key] = [item];
    }
  }
  return result;
}

const booksByTitle = groupBy(data, "title");

console.log(booksByTitle);
.as-console-wrapper{top:0;max-height:100%!important}