Создание вложенных массивов заданной структуры - PullRequest
0 голосов
/ 25 августа 2018

У меня есть массив объектов с именованными ключами следующим образом:

Array1 [
  {
    'town1': 'London', // string
    'town2': 'Paris', // string
    'distance': 123456, // number
  },
  {
    'town1': 'Seoul', // string
    'town2': 'Tokio', // string
    'distance': 654321, // number
  },
  {},{},... // Objects with same properties
]

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

Array2 [
  [{ name: 'town1', value: 'distance'}, { name: 'town2'}],
  [{ name: 'town1', value: 'distance'}, { name: 'town2'}],
  [{...}, {...}],   // All other objects with existing town1-town2-distance
]

Как этого добитьсясамым эффективным и быстрым способом?

Ответы [ 4 ]

0 голосов
/ 25 августа 2018

Хорошо, я тоже хочу попробовать! Почему никто не думал о снижении? Это быстрее, чем для цикла! И более элегантно. ИМО как минимум.

Итак, я провел несколько тестов, и вот результаты:

enter image description here

И вот код:

1) Array.prototype.reduce() с Array.prototype.push()

const array2 = array1.reduce((arr, obj) => {
  if (obj.hasOwnProperty('town1') && obj.hasOwnProperty('town2') && obj.hasOwnProperty('value')) {
    arr.push([ { name: obj.town1, value: obj.distance }, { name: obj.town2 } ])
  }

  return arr
}, [])

2) Array.prototype.reduce() с Array.prototype.concat()

const array2 = array1.reduce((arr, obj) => (
  (obj.hasOwnProperty('town1') && obj.hasOwnProperty('town2') && obj.hasOwnProperty('value'))
    ? Array.prototype.concat(arr, [[ { name: obj.town1, value: obj.distance }, { name: obj.town2 } ]])
    : arr
  ), [])

3) Array.prototype.reduce() с оператором спреда

array2 = array1.reduce((arr, obj) => (
  (obj.hasOwnProperty('town1') && obj.hasOwnProperty('town2') && obj.hasOwnProperty('value'))
    ?  [...arr, [ { name: obj.town1, value: obj.distance }, { name: obj.town2 } ]]
    : arr
  ), [])

4) И @Emueeus идти. For-loop с Array.prototype.push()

for (let i = 0; i<array1.length; i++) {
  if (array1[i].hasOwnProperty('town1') && array1[i].hasOwnProperty('town2') && array1[i].hasOwnProperty('distance')) {
    array2.push([{name:array1[i]['town1'], value: array1[i]['distance']}, { name: array1[i]['town2']}])
  }
}

Вот тест: http://jsfiddle.net/4bca0g2u/

0 голосов
/ 25 августа 2018

Решение MinusFour является почти правильным.Вы также хотели бы отфильтровать элементы, которые на самом деле имеют необходимые ключи:

Array2.filter(obj => obj.hasOwnProperty("town1") &&
                     obj.hasOwnProperty("town2") &&
                     obj.hasOwnProperty("distance"))
      .map(obj => [{ name: obj.town1, value: obj.distance }, { name: obj.town2 }]);

Это то, что вы ищете?

0 голосов
/ 25 августа 2018

Всего одна итерация (O (n)) с использованием for.Это быстрее, чем фильтр и карта (2 итерации). https://jsperf.com/mapfiltervsfor/1

var array1 = [
    {
      'town1': 'London', // string
      'town2': 'Paris', // string
      'distance': 123456, // number
    },
    {
      'town1': 'Seoul', // string
      'town2': 'Tokio', // string
      'distance': 654321, // number
    }
  ];

  var array2 = [];

  for(let i = 0; i<array1.length; i++){

     if(array1[i].hasOwnProperty('town1') &&  array1[i].hasOwnProperty('town2') && array1[i].hasOwnProperty('distance')){
        array2.push([{name:array1[i]['town1'], value: array1[i]['distance']}, { name: array1[i]['town2']}])
     }

  }
  console.log(array2)
0 голосов
/ 25 августа 2018

Похоже, что один map будет работать для вас.

let mustHave = ['town1', 'town2', 'distance'];
Array1.filter(obj => mustHave.every(key => obj.hasOwnProperty(key))
      .map(obj => [{ name : obj.town1, value: obj.distance}, { name : obj.town2 }])

Edit: не видел, что вы не хотите отображать объекты без этих ключей. Об этом позаботится фильтр.

...