#javascript
#javascript
Вопрос:
Мне нужно преобразовать следующий массив объектов в формат объекта, когда topic = ‘избранное’.
Исходный формат
const events = [
{
topic: 'favorites',
receiver: '1000066928',
datetime: 2016-11-26T21:43:54.000Z
},
{
topic: 'favorites',
receiver: '1000061499',
datetime: 2017-01-03T19:15:04.000Z
},
{
topic: 'blocked',
receiver: '1000102733',
datetime: 2017-01-05T17:04:15.000Z
},
{
topic: 'blocked',
receiver: '1000107928',
datetime: 2017-01-06T17:17:05.000Z
}
]
Преобразованный формат
{
1000000002: '2020-01-24T20:46:05 11:00',
1000000008: '2020-01-24T20:46:05 11:00',
1000000009: '2020-01-24T20:46:05 11:00',
1000000010: '2020-01-24T20:46:05 11:00'
},
Я пытался работать со следующим, но у меня немного не получается.
events.filter((event) => event.topic === "favorites").map(receiver, datetime => receiver: datetime)
Комментарии:
1. как вы получаете результат из заданных данных?
2. Это то, что я пытаюсь тренировать… Мне нужно перейти от исходного формата к преобразованному формату
3. Синтаксис на
map
неправильный, он должен быть{ receiver, datetime }
Ответ №1:
Вы можете отфильтровать и сопоставить записи для нового объекта.
const
events = [{ topic: 'favorites', receiver: '1000066928', datetime: '2016-11-26T21:43:54.000Z' }, { topic: 'favorites', receiver: '1000061499', datetime: '2017-01-03T19:15:04.000Z' }, { topic: 'blocked', receiver: '1000102733', datetime: '2017-01-05T17:04:15.000Z' }, { topic: 'blocked', receiver: '1000107928', datetime: '2017-01-06T17:17:05.000Z' }],
result = Object.fromEntries(events
.filter(({ topic }) => topic === 'favorites')
.map(({ receiver, datetime }) => [receiver, datetime])
);
console.log(result);
Ответ №2:
Предоставленные вами данные не соответствуют ожидаемому результату по значению. Но я предполагаю, что формат правильный. Также кажется, что в вашем результате вам нужны даты в форме строки ISO. Но в вашем исходном объекте они хранятся как Date
объект. Поэтому я предполагаю, что исходный массив действительно содержит Date
объекты.
С учетом сказанного, вам действительно просто нужно превратить каждый объект в [receiver, datetime]
(после фильтрации) и сделать Object.fromEntries
с результатом
const result = Object.fromEntries(
events
.filter(event => event.topic === 'favorites')
.map(({ receiver, datetime }) => [receiver, datetime.toISOString()])
);
const events = [
{
topic: 'favorites',
receiver: '1000066928',
datetime: new Date('2016-11-26T21:43:54.000Z'),
},
{
topic: 'favorites',
receiver: '1000061499',
datetime: new Date('2017-01-03T19:15:04.000Z'),
},
{
topic: 'blocked',
receiver: '1000102733',
datetime: new Date('2017-01-05T17:04:15.000Z'),
},
{
topic: 'blocked',
receiver: '1000107928',
datetime: new Date('2017-01-06T17:17:05.000Z'),
},
];
const result = Object.fromEntries(
events
.filter(event => event.topic === 'favorites')
.map(({ receiver, datetime }) => [receiver, datetime.toISOString()])
);
console.log(result);
Ответ №3:
Должно быть достаточно однострочного редуктора
const events = [{
topic: 'favorites',
receiver: '1000066928',
datetime: "2016-11-26T21:43:54.000Z"
},
{
topic: 'favorites',
receiver: '1000061499',
datetime: "2017-01-03T19:15:04.000Z"
},
{
topic: 'blocked',
receiver: '1000102733',
datetime: "2017-01-05T17:04:15.000Z"
},
{
topic: 'blocked',
receiver: '1000107928',
datetime: "2017-01-06T17:17:05.000Z"
}
]
console.log(events
.reduce((acc, val) => val.topic === "favorites" amp;amp;
{ ...acc, [val.receiver]: val.datetime } ||
acc, {}));
Комментарии:
1. Я нахожу это выражение
<condition> amp;amp; <if true> || <if false>
немного неинтуитивным. Использование троичного оператора кажется более идиоматичным :<condition> ? <if true> : <if false>
.2. Я полагаю, это вопрос использования: если код доступен другим пользователям, читаемость может быть важна. В этом случае я бы действительно выбрал
if (val.topic === "favorites") {...} else {...}
. В противном случае логическое короткое замыкание или троичное (в данном случае) эквивалентны.
Ответ №4:
С reduce
помощью вы можете создать объект, который будет обновляться на каждой итерации.
const output = events
.filter((event) => event.topic === "favorites")
.reduce((acc, cur) => {
return {...acc, [cur.receiver]: cur.datetime };
}, {});
console.log(output);
/* {
'1000061499': '2017-01-03T19:15:04.000Z',
'1000066928': '2016-11-26T21:43:54.000Z'
}
*/
Ответ №5:
вы можете использовать reduce и filter для этого в комбинации
Мне пришлось сделать строку из datetime, иначе это привело бы к ошибке.
const events = [
{
topic: 'favorites',
receiver: '1000066928',
datetime: "2016-11-26T21:43:54.000Z"
},
{
topic: 'favorites',
receiver: '1000061499',
datetime: "2017-01-03T19:15:04.000Z"
},
{
topic: 'blocked',
receiver: '1000102733',
datetime: "2017-01-05T17:04:15.000Z"
},
{
topic: 'blocked',
receiver: '1000107928',
datetime: "2017-01-06T17:17:05.000Z"
}
]
const result = events
.filter((event) => event.topic === "favorites")
.reduce((accum, element) => {
return {...accum, [element.receiver]: element.datetime };
}, {});
console.log(result);
Ответ №6:
Вы можете использовать reduce
так:
const filteredEvents = events.reduce((a, b) => {
return b.topic === 'favorites'
? {...a, [b.receiver] : b.datetime}
: a
}, {})
console.log(filteredEvents);
/*
{
'1000061499': '2017-01-03T19:15:04.000Z',
'1000066928': '2016-11-26T21:43:54.000Z'
}
*/
Ответ №7:
Это классический вариант использования функции .reduce()
прототипа для массива. Это сэкономит вам несколько повторяющихся итераций с меньшим количеством строк кода.
Данные примера, похоже, не совпадают, но я предполагаю, что формат правильный.
В вашем случае вы можете использовать reduce
так —
const events = [
{
topic: 'favorites',
receiver: '1000066928',
datetime: new Date('2016-11-26T21:43:54.000Z'),
},
{
topic: 'favorites',
receiver: '1000061499',
datetime: new Date('2017-01-03T19:15:04.000Z'),
},
{
topic: 'blocked',
receiver: '1000102733',
datetime: new Date('2017-01-05T17:04:15.000Z'),
},
{
topic: 'blocked',
receiver: '1000107928',
datetime: new Date('2017-01-06T17:17:05.000Z'),
},
];
const result = events.reduce((acc, event) => {
if (b.topic === 'favorites') {
return {...acc, [event.receiver] : b.datetime};
}
return acc;
}, {})
console.log(result);
Чтобы лучше понять, как работает reduce — https://www.freecodecamp.org/news/reduce-f47a7da511a9 /
Ответ №8:
Одного сокращения в сочетании с фильтром темы должно быть достаточно, и некоторые ответы уже продемонстрировали, как это сделать.
Этот ответ делает это, но добавляет:
- Каррирование. Таким образом, вы можете применить преобразование к другим темам
- Оператор запятой вместо оператора распространения. В зависимости от размера обрабатываемого списка оператор spread может быстро стать узким местом в производительности
const transform =
topic => xs =>
xs.reduce( (o, x) =>
(x.topic === topic
? (o[x.receiver] = x.datetime, o)
: o), {});
Что здесь происходит?
Функция обработана; для обработки требуется тема, а затем список. Это означает, что вы можете создать две функции обработки тем:
const favorites = transform('favorites');
const blocked = transform('blocked');
Эти две функции теперь ожидают только обработки списка. Предполагается list
, что это то же самое, что и ваш events
массив:
favorites(list);
// { 1000061499: "2017-01-03T19:15:04.000Z"
// , 1000066928: "2016-11-26T21:43:54.000Z"
// }
blocked(list);
// { 1000102733: "2017-01-05T17:04:15.000Z"
// , 1000107928: "2017-01-06T17:17:05.000Z"
// }