Объединить последовательные объекты в один массив на основе условия - PullRequest
0 голосов
/ 17 июня 2019

Я хотел бы объединить последовательные объекты данных в массиве на основе условий. У меня есть маршрутный массив, где каждый объект является участком этой поездки. Рассмотрим следующие примеры:

Поездка 1: WALK - WALK - WALK - VEHICLE - WALK - VEHICLE - WALK ^ short transfer

Поездка 2: WALK - WALK - WALK - VEHICLE - WALK - WALK - VEHICLE - WALK - VEHICLE

Поездка 3: WALK - WALK - VEHICLE - WALK - WALK


То, что я хотел бы сделать, это объединить WALK ветви, если они последовательные (сразу после друг друга), в одну WALK ногу, охватывающую объединенные части, см. Ниже:

Поездка 1: WALK - VEHICLE - WALK - VEHICLE - WALK ^ short transfer

Поездка 2: WALK - VEHICLE - WALK - VEHICLE - WALK - VEHICLE

Поездка 3: WALK - VEHICLE - WALK


Каждый объект ноги выглядит примерно так:

{
    mode: 'WALK', // or VEHICLE
    to: { ... },
    from: { ... }
}

Я пытался использовать .reduce() и с помощью его текущей индексной группы объектов объединить разные детали, но безуспешно. Я даже не знаю, правильная ли это функция.

const oldTrip = [
	{ mode: 'WALK' },
	{ mode: 'WALK' },
	{ mode: 'VEHICLE' },
	{ mode: 'VEHICLE' },
	{ mode: 'WALK' }
];

let previousWalk = false;
const newTrip = oldTrip.reduce((acc, cur, idx) => {
  if (cur.mode === 'VEHICLE') previousWalk = false;
  else {
    if (previousWalk) {
      
    }
    previousWalk = true;
  }
  return acc;
});

Любая помощь или толчок в правильном направлении очень ценится!

Ответы [ 5 ]

2 голосов
/ 17 июня 2019

Вместо redu () я использую filter () с индексом, к счастью, мы не можем столкнуться с OutOfBound, как это. Мы проверяем повторы только тогда, когда у нас есть "WALK" в качестве текущего элемента. Я добавил четвертый пример, чтобы показать, что повторения, не связанные с прогулкой, не фильтруются.

function filterRepWalk(a) {
  return a.filter((v,i) => v != "WALK" || v != a[i-1]);
}

console.log(filterRepWalk(["WALK", "WALK", "WALK", "VEHICLE", "WALK",  "VEHICLE", "WALK"]));
console.log(filterRepWalk(["WALK", "WALK", "WALK", "VEHICLE", "WALK", "WALK", "VEHICLE", "WALK", "VEHICLE"]));
console.log(filterRepWalk(["WALK", "WALK", "VEHICLE", "WALK", "WALK"]));
console.log(filterRepWalk(["WALK", "WALK", "WALK", "VEHICLE", "WALK", "WALK", "VEHICLE", "WALK", "VEHICLE", "VEHICLE"]));

И для того же на объекте выполняются следующие действия:

function filterRepWalk(a) {
  return a.filter((v,i) => (!a[i-1] || (v.mode != a[i-1].mode)) || v.mode != "WALK");
}
2 голосов
/ 17 июня 2019

Array#reduce вернет вам одно значение.

Используйте вместо этого Array#filter, сравнив последнее итерированное значение с текущим.

const steps = [
  { mode: 'WALK' },
  { mode: 'WALK' },
  { mode: 'VEHICLE' },
  { mode: 'VEHICLE' },
  { mode: 'WALK' },
  { mode: 'VEHICLE' },
  { mode: 'VEHICLE' },
  { mode: 'VEHICLE' },
  { mode: 'WALK' },
  { mode: 'WALK' },
  { mode: 'VEHICLE' },
  { mode: 'VEHICLE' },
  { mode: 'WALK' }
];

console.log(

steps.filter((s, i, self) => (
  !self[i + 1]
    || s.mode === 'VEHICLE'
    || self[i + 1].mode !== s.mode
  ))

);
1 голос
/ 17 июня 2019

Вы можете выполнить деструктурирование с помощью параметра массива Array.filter и получить краткое решение, например:

let filter = (arr, str) => arr.filter((x,i,{[i-1]:k}) => x != str || x != k)

console.log(filter(["WALK", "WALK", "VEHICLE"], 'WALK'));
console.log(filter(["VEHICLE", "VEHICLE", "WALK"], 'VEHICLE'));

Теперь вы также можете передать любую из строк, которые хотите объединить.

0 голосов
/ 17 июня 2019

const oldTrip = [
    { mode: 'WALK' },
    { mode: 'WALK' },
    { mode: 'VEHICLE' },
    { mode: 'VEHICLE' },
    { mode: 'WALK' }
];

const newTrip = oldTrip.reduce((acc, cur) => {
    if (cur.mode === 'WALK' && acc.length && acc[acc.length - 1].mode === 'WALK') {
        return acc;
    }
    acc.push(cur);
    return acc;
}, []);

console.log(newTrip);
0 голосов
/ 17 июня 2019

Вы можете использовать этот подход, который использует Array.prototype.reduce, как вы упомянули:

const getDirections = str => {
  //Split the string into an array and remove the whitespace
  const data = str.split('-').map(el => el.replace(/\s/g, ''));

  //Add to the accumulator if the prior element is different
  return data.reduce((accum, el, idx, arr) => {
    if (el !== accum[accum.length - 1]) {
      accum.push(el);
    }
    return accum;
  }, []);
}


const directions = getDirections("WALK - WALK - WALK - VEHICLE - WALK - WALK - VEHICLE - WALK - VEHICLE");

console.log(directions);
...