Преобразование массива в массив объектов с уменьшением
optimizedRoute = ['Bengaluru', 'Salem', 'Erode', 'Tiruppur', 'Coimbatore']
result = [
{start: bengaluru, end: salem},
{start: salem, end: erode},
{start: erode, end: tiruppur},
{start: tiruppur, end: coimbatore},
]
Я хочу преобразовать optimizedRoute
в результат. Я хочу сделать это с помощью ES6 .reduce()
. Вот что я пробовал:
const r = optimizedRoute.reduce((places, place, i) => {
const result: any = [];
places = []
places.push({
startPlace: place,
endPlace: place
});
// result.push ({ startplace, endplace, seats: 4 });
// console.log(result);
return places;
}, {});
console.log(r)
Ответы
Ответ 1
Вы можете использовать reduce
для получения начальной и конечной части маршрута и вернуть конец для следующего запуска.
getParts = a => ( // take a as array and return an IIFE
r => ( // with an initialized result array
a.reduce((start, end) => ( // reduce array by taking two values
r.push({ start, end }), // push short hand properties
end // and take the last value as start value for next loop
)),
r // finally return result
)
)([]); // call IIFE with empty array
const getParts = a => (r => (a.reduce((start, end) => (r.push({ start, end }), end)), r))([]);
var optimizedRoute = ['Bengaluru', 'Salem', 'Erode', 'Tiruppur', 'Coimbatore']
console.log(getParts(optimizedRoute));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Ответ 2
Я действительно не понимаю требования "с уменьшением", так как соответствующий код с использованием цикла сразу читается и не требует объяснений:
const optimizedRoute = ['Bengaluru', 'Salem', 'Erode', 'Tiruppur', 'Coimbatore'];
const result = new Array(optimizedRoute.length - 1);
for (let i = 0; i < result.length; ++i) {
result[i] = {
start: optimizedRoute[i],
end: optimizedRoute[i + 1]
};
}
console.log(result)
Ответ 3
Другой подход - использовать метод map
в сочетании с slice
. Для функции map
вам необходимо передать функцию callback
качестве аргумента, который будет применяться для каждого элемента из данного массива.
optimizedRoute = ['Bengaluru', 'Salem', 'Erode', 'Tiruppur', 'Coimbatore']
var result = optimizedRoute
.slice(0, -1)
.map((item, index) => ({start : item, end : optimizedRoute[index + 1]}));
console.log(result);
Ответ 4
Вот пример с reduce
. Я не уверен, что это самый естественный способ сделать это!
Использование reduce
чувствует себя излишним и в таком случае (но это только мое мнение), где я, естественно, использовать индекс, ну, я бы пойти на простой for
цикла.
const optimizedRoute = ['Bengaluru', 'Salem', 'Erode', 'Tiruppur', 'Coimbatore'];
let startCity;
const result = optimizedRoute.reduce((acc, city) => {
if(startCity) {
acc.push({start: startCity, end: city});
}
startCity = city;
return acc;
}, []);
console.log(result);
Ответ 5
Поскольку вы попросили reduce
, вот один из способов сделать это:
let optimizedRoute = ['Bengaluru', 'Salem', 'Erode', 'Tiruppur', 'Coimbatore']
let res = optimizedRoute.reduce((accum, item, i)=>{
if(i == optimizedRoute.length - 1)
return accum;
accum.push({start: item, end: optimizedRoute[i+1]})
return accum;
}, [])
console.log(res);
Ответ 6
reduce
действительно не соответствует законопроекту здесь, поскольку вы не пытаетесь уменьшить массив до одного значения.
В идеальном мире мы бы мульти-массив map
версии, обычно известный как zip
, что мы могли бы использовать как
const result = zipWith(optimisedRoute.slice(0, -1),
optimisedRoute.slice(1),
(start, end) => ({start, end}));
но в JavaScript нет. Лучшей альтернативой является map
по диапазону индексов в маршрут с использованием Array.from
:
const result = Array.from({length: optimisedRoute.length - 1}, (_, index) => {
const start = optimisedRoute[index];
const end = optimisedRoute[index + 1];
return {start, end};
});
Ответ 7
Следующий код использует Spread operator
, Ternary operator
Array.reduce
и Array.reduce
.
const optimizedRoute = [
'Bengaluru',
'Salem',
'Erode',
'Tiruppur',
'Coimbatore',
];
// Look if we are at dealing with the last value or not
// If we do only return the constructed array
// If we don't, add a new value into the constructed array.
// tmp is the array we are constructing
// x the actual loop item
// xi the index of the item
const lastItemIndex = optimizedRoute.length - 1;
const ret = optimizedRoute.reduce((tmp, x, xi) => xi !== lastItemIndex ? [
...tmp,
{
start: x,
// We access to the next item using the position of
// the current item (xi)
end: optimizedRoute[xi + 1],
},
] : tmp, []);
console.log(ret);
Ответ 8
Я упростил ответ nina academz. В соответствии с идеей ninas используйте сокращение для начала и конца части маршрута и верните конец для следующего запуска.
getParts = a => {
const result = [];
a.reduce((start, end) => {
result.push({ start, end });
return end;
});
return result;
};
var optimizedRoute = ['Bengaluru', 'Salem', 'Erode', 'Tiruppur', 'Coimbatore'];
console.log(this.getParts(optimizedRoute));
Ответ 9
Я предпочитаю читаемость по простому короткому коду, который его решает
optimizedRoute.reduce((routes, city, index) => {
const firstCity = index === 0;
const lastCity = index === optimizedRoute.length - 1;
if (!firstCity) {
routes.last().end = city;
}
if (!lastCity) {
routes.push({ start: city });
}
return routes;
}, []);
Кроме того, это решение уменьшило читаемость (хотя бы для меня), может быть:
optimizedRoute.reduce((routes, city) => {
routes.last().start = city;
routes.push({ end: city });
return routes;
}, [{}]).slice(1, -1);
И о last()
, это функция, которую я обычно использую для удобочитаемости:
Array.prototype.last = function() {
return this[this.length - 1]
}
Ответ 10
Решение с помощью ReduceRight, если кто-то ищет.
optimizedRoute.reduceRight((acc, d, i, arr) =>
i == 0
? acc
: [{ start: arr[i -1], end: d }, ...acc]
, [])