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.info(result);
return places;
}, {});
console.info(r)



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Следующий код использует Spread operator, Ternary operator и 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.info(ret);Поскольку вы просили 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.info(res);Другой подход - использовать метод 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.info(result);Вот пример с 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.info(result);Вы можете использовать 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.info(getParts(optimizedRoute));.as-console-wrapper { max-height: 100% !important; top: 0; }@РЕДАКТИРОВАТЬ Грегори НЕЙТ добавление объяснения
// Two thing to know first :
// When no initial value is provided,
// Array.reduce takes the index 0 as first value and start to loop at index 1
// Doing (x, y, z)
// Will execute the code x, y and z
// Equivalent to :
// x;
// y;
// z;
let ex = 0;
console.info((ex = 2, ex = 5, ex = 3));
// So about the code
const getParts = (a) => {
// We are creating a new function here so we can have an array where to
// push data to
const func = (r) => {
// Because there is no initial value
//
// Start will be the value at index 0 of the array
// The loop is gonna start at index 1 of the array
a.reduce((start, end) => {
console.info(start, end);
r.push({
start,
end,
});
return end;
});
return r;
};
return func([]);
};
// Equivalent
const getPartsEquivalent = (a) => {
const r = [];
// Because there is no initial value
//
// Start will be the value at index 0 of the array
// The loop is gonna start at index 1 of the array
a.reduce((start, end) => {
console.info(start, end);
r.push({
start,
end,
});
return end;
});
return r;
};
var optimizedRoute = ['Bengaluru', 'Salem', 'Erode', 'Tiruppur', 'Coimbatore']
console.info(getPartsEquivalent(optimizedRoute));.as-console-wrapper {
max-height: 100% !important;
top: 0;
}Несмотря на то, что это может быть (хорошее) решение, я думаю, что OP слишком сложно понять данные навыки OP.
Нина, не могли бы вы добавить еще немного подробностей, чтобы объяснить шаги этого замечательного однострочного сообщения?
@Nina Scholz Я не могу понять, почему первое значение не является { start: undefined, end: 'Bengaluru',} . Это что-то о сокращении, игнорирующем первое значение, когда нет начального значения?
У меня есть ответ здесь, первое значение - это значение индекса 0, когда начальное значение не указано (и цикл начинается с 1).
@ GrégoryNEUT, верно, если сокращение не начинается с начального значения, то первые два элемента берутся как аккумулятор и элемент. индекс начинается с 1. для иллюстрации вы можете попробовать это: [4, 5, 6, 7].reduce((a, b, i) => (console.info(i, a, b), b));
@NinaScholz Спасибо. Я позволил себе пояснить ваш код. Потому что это может быть сложно понять. Конечно, это ваш пост и ваш ответ, я полностью понимаю, хотите ли вы изменить или удалить то, что я добавил.
@nina scholz, спасибо за ваши решения. Почему вы используете закрытие в своем решении?
вам нужна переменная для результата, и если вы не хотите объявлять в теле, вы можете использовать закрытие / IIFE для переменной. но реальный ответ: мне нравится стиль ;-)
@NinaScholz Я не знал о синтаксисе (a, b, c), в котором все выражения оцениваются, но возвращается последнее! Это довольно круто в такой ситуации, спасибо вам большое!
@sjahan, это оператор запятой, но на самом деле мне интересно, где он в моем коде?
@NinaScholz в функции reducer, вы используете его для возврата end: (r.push({ start, end }), end). Вот что меня поначалу озадачило! Очень рад, что обнаружил это благодаря вам :)
верно, этот шаблон присутствует в коде два раза: один для возврата end, а другой для возврата результата r.
Я упростил ответ Нины Шольц, По идее Нины, используйте сокращение для получения начальной и конечной части маршрута и верните конец для следующего старта.
getParts = a => {
const result = [];
a.reduce((start, end) => {
result.push({ start, end });
return end;
});
return result;
};
var optimizedRoute = ['Bengaluru', 'Salem', 'Erode', 'Tiruppur', 'Coimbatore'];
console.info(this.getParts(optimizedRoute));
Я не совсем понимаю требование «с сокращением», поскольку соответствующий код, использующий цикл, сразу читается и не требует пояснений:
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.info(result)Иногда делать умные вещи интересно, но некоторые ответы очень сложны по сравнению с этим!
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};
});
Этот подход очень похож на то, что сделали Михай Александру-Ионут и Том Фенек, вы также должны проголосовать за их ответы!
@saila Упс, исправлено. Процесс довольно прост, Array.from({length: …}, …) - это известный трюк, который в основном эквивалентен range(0, …).map(…).
@ Bergi, что лучше всего согласно обозначениям.
@saila Я думаю, что все представленные здесь решения имеют линейное время выполнения
Я предпочитаю читабельность больше короткий код, который ее решает
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]
}
Решение с ReduceRight, если кто ищет.
optimizedRoute.reduceRight((acc, d, i, arr) =>
i == 0
? acc
: [{ start: arr[i -1], end: d }, ...acc]
, [])
Пожалуйста, объясните, почему здесь голосование вниз, я добавил этот ответ, если кто-то ищет решение с помощью reduceRight (которое похоже на сокращение). Спасибо.
Это впечатляет, но сложно это понять!