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

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)
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
24
0
7 350
10
Перейти к ответу Данный вопрос помечен как решенный

Ответы 10

Следующий код использует 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;
}

Это впечатляет, но сложно это понять!

sjahan 18.07.2018 10:22

Несмотря на то, что это может быть (хорошее) решение, я думаю, что OP слишком сложно понять данные навыки OP.

giorgi moniava 18.07.2018 10:35

Нина, не могли бы вы добавить еще немного подробностей, чтобы объяснить шаги этого замечательного однострочного сообщения?

sjahan 18.07.2018 10:36

@Nina Scholz Я не могу понять, почему первое значение не является { start: undefined, end: 'Bengaluru',} . Это что-то о сокращении, игнорирующем первое значение, когда нет начального значения?

Orelsanpls 18.07.2018 10:47

У меня есть ответ здесь, первое значение - это значение индекса 0, когда начальное значение не указано (и цикл начинается с 1).

Orelsanpls 18.07.2018 10:53

@ GrégoryNEUT, верно, если сокращение не начинается с начального значения, то первые два элемента берутся как аккумулятор и элемент. индекс начинается с 1. для иллюстрации вы можете попробовать это: [4, 5, 6, 7].reduce((a, b, i) => (console.info(i, a, b), b));

Nina Scholz 18.07.2018 10:53

@NinaScholz Спасибо. Я позволил себе пояснить ваш код. Потому что это может быть сложно понять. Конечно, это ваш пост и ваш ответ, я полностью понимаю, хотите ли вы изменить или удалить то, что я добавил.

Orelsanpls 18.07.2018 11:01

@nina scholz, спасибо за ваши решения. Почему вы используете закрытие в своем решении?

kartik 18.07.2018 13:08

вам нужна переменная для результата, и если вы не хотите объявлять в теле, вы можете использовать закрытие / IIFE для переменной. но реальный ответ: мне нравится стиль ;-)

Nina Scholz 18.07.2018 13:12

@NinaScholz Я не знал о синтаксисе (a, b, c), в котором все выражения оцениваются, но возвращается последнее! Это довольно круто в такой ситуации, спасибо вам большое!

sjahan 18.07.2018 15:37

@sjahan, это оператор запятой, но на самом деле мне интересно, где он в моем коде?

Nina Scholz 18.07.2018 18:18

@NinaScholz в функции reducer, вы используете его для возврата end: (r.push({ start, end }), end). Вот что меня поначалу озадачило! Очень рад, что обнаружил это благодаря вам :)

sjahan 18.07.2018 18:33

верно, этот шаблон присутствует в коде два раза: один для возврата end, а другой для возврата результата r.

Nina Scholz 18.07.2018 18:37

Я упростил ответ Нины Шольц, По идее Нины, используйте сокращение для получения начальной и конечной части маршрута и верните конец для следующего старта.

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};
});

Этот подход очень похож на то, что сделали Михай Александру-Ионут и Том Фенек, вы также должны проголосовать за их ответы!

Bergi 18.07.2018 20:20

@saila Упс, исправлено. Процесс довольно прост, Array.from({length: …}, …) - это известный трюк, который в основном эквивалентен range(0, …).map(…).

Bergi 19.07.2018 18:33

@ Bergi, что лучше всего согласно обозначениям.

kartik 21.07.2018 06:41

@saila Я думаю, что все представленные здесь решения имеют линейное время выполнения

Bergi 21.07.2018 14:19

Я предпочитаю читабельность больше короткий код, который ее решает

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 (которое похоже на сокращение). Спасибо.

Nitish Narang 17.10.2018 10:34

Другие вопросы по теме