Преобразование массива в массив объектов с уменьшением

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]  
            , [])