Улучшение вложенного forEach

#javascript #arrays #loops #foreach

#javascript #массивы #циклы #foreach

Вопрос:

У меня есть этот вложенный массив:

 const users = [
    ['User_1', [[1596232800000, 4]]],
    [
        'User_2',
        [
            [1591567200000, 3],
            [1591653600000, 16],
        ],
    ],
]

  

и хотел бы, чтобы этот вывод:

 const dataByDate = [
    {
        user: 'User_2',
        date: 1591567200000,
        count: 3,
    },
    {
        user: 'User_2',
        date: 1591653600000,
        count: 16,
    },
    {
        user: 'User_1',
        date: 1596232800000,
        count: 4,
    },
]
  

Для достижения этой цели я делаю это:

 
    const dataByDate: { date: string; count: number; user: string }[] = []

    users.forEach((user: string[]) => {
        if (user[1].length) {
            user[1].forEach((item: any) => {
                dataByDate.push({ date: item[0], user: user[0], count: item[1] })
            })
        }
    })

  

Мое решение работает нормально, но мне интересно, есть ли более чистое и элегантное решение, чем вложенный forEach . Спасибо!

Комментарии:

1. Array.prototype.flatMap()

2. Имеет ли значение порядок?

3. В идеале это должно быть упорядочено по количеству

4. @suuuriam значит, ваш выходной массив находится в неправильном порядке?

Ответ №1:

Вы можете использовать .flatMap с внутренним .map() . Внутренний .map() возьмет второй элемент вашего внутреннего массива (т. Е. [[date, count], ...] Массивы) и сопоставит их с объектами. Поскольку .map() результатом будет массив объектов, вы можете использовать .flatMap() для объединения результирующих объектов в один конечный результирующий массив.

Смотрите пример ниже:

 const users = [
    ['User_1', [[1596232800000, 4]]],
    [
        'User_2',
        [
            [1591567200000, 3],
            [1591653600000, 16],
        ],
    ],
];

const result = users.flatMap(([user, arr]) => arr.map(([date, count]) => ({
  user, date, count
})));
console.log(result);  

Затем вы можете применить .sort() метод для любого дополнительного переупорядочения выходного массива.

Ответ №2:

Используйте комбинацию Array.prototype.flatMap() и Array.prototype.reduce() . Сокращение перебирает каждый набор данных для пользователя и создает объект and для каждой записи в этом наборе. Затем этот объект объединяется в накопительный массив.

Теперь flatMap возвращает новый массив с объектами для каждого пользователя. Количество объектов зависит от количества [date, count] записей и будет находиться во вложенном массиве. Плоская часть flatMap заботится об этом, помещая каждый объект в один массив.

 const users = [
  [
    'User_1', [
      [1596232800000, 4]
    ]
  ],
  [
    'User_2', [
      [1591567200000, 3],
      [1591653600000, 16],
    ],
  ],
];

const formatUserData = users => users.flatMap(([ user, data ]) => 
  data.reduce((arr, [ date, count ]) => 
    [...arr, { user, date, count }], [])
  );
  
const result = formatUserData(users);

console.log(result);  

Ответ №3:

Используя карту и деструктурирование массива, вы можете добиться этого следующим образом:

 const result = users
   .map(([ user, items ]) => {
      return items.flatMap(([date, count]) => ({ user, date, count }))
   })
   .flatMap(i => i)
   .sort((a,b) => a.date - b.date);
  

 const users = [
        ['User_1', [[1596232800000, 4]]],
        [
            'User_2',
            [
                [1591567200000, 3],
                [1591653600000, 16],
            ],
        ],
    ]

const result = users.map(([ user, items ]) => {
  return items.flatMap(([date, count]) => ({ user, date, count }))
}).flatMap(i => i).sort((a,b) => a.date - b.date);

console.log({result})