Первый массив представляет собой основной список объектов даты, содержащих уникальные объекты даты в JavaScript:

[
   {'date': dateobject1, 'value': null},
   {'date': dateobject2, 'value': null},
   {'date': dateobject3, 'value': null},
   etc...
]

Первый массив - это гораздо меньший список объектов даты, содержащий подмножество уникальных объектов Date в javascript, причем свойство 'value' всегда имеет число, а не null:

[
   {'date': dateobject3, 'value': 3117},
   {'date': dateobject8, 'value': 14},
   etc...
]

Учитывая нюансы сравнения объектов даты - https://stackoverflow.com/a/493018/538962 - что бы быть наиболее эффективным способом объединения этих объектов - в среде, где доступен lodash 3.10.1 - на основе сопоставленных дат, чтобы объединенный массив представлял собой список всех дат: совпадения означают, что «значение» становится числовым значением, а в противном случае null «значение» сохраняется, когда совпадения нет?

[
   {'date': dateobject1, 'value': null},
   {'date': dateobject2, 'value': null},
   {'date': dateobject3, 'value': 3117},
   {'date': dateobject4, 'value': null},
   {'date': dateobject5, 'value': null},
   {'date': dateobject6, 'value': null},
   {'date': dateobject7, 'value': null},
   {'date': dateobject8, 'value': 14},
   etc...
]
4
mg1075 30 Авг 2017 в 03:01

3 ответа

Лучший ответ

Вы можете использовать встроенный Array.prototype.map , чтобы создать новый массив из существующих значений массива.

Где вы говорите:

Первый массив - это гораздо меньший список объектов даты, содержащий подмножество уникальных объектов Date в JavaScript.

Я предполагаю, что dateobject3 - это один и тот же объект в обоих массивах, а не два разных объекта для одной и той же даты.

Далее создается индекс для массива values для сохранения итерации по значениям для каждого члена data . Это не будет иметь заметного значения для небольших наборов данных (скажем, менее 100 значений), но будет для более крупных (скажем, более нескольких сотен или тысяч).

var d0 = new Date(2017,1,1),
    d1 = new Date(2017,1,2),
    d2 = new Date(2017,1,3);

var data = [
   {'date': d0, 'value': null},
   {'date': d1, 'value': null},
   {'date': d2, 'value': null}
];

var values = [
   {'date': d1, 'value': 3117},
];

// Generate a values index, saves searching
// through values for each member of data
var indexes = values.map(obj => obj.date);
// Generate merged array
var merged = data.map(obj => {
  var index = indexes.indexOf(obj.date); 
  return {date: obj.date, value: index > -1? values[index].value : obj.value};
});

console.log(merged)

Если, с другой стороны, даты - это разные объекты, но с одинаковым значением времени, вам нужно вместо этого сравнить значение времени. Простой способ получить значение времени - использовать унарный +, он просто сохраняет ввод с помощью getValue или getTime :

var data = [
   {'date': new Date(2017,1,1), 'value': null},
   {'date': new Date(2017,1,2), 'value': null},
   {'date': new Date(2017,1,3), 'value': null}
];

var values = [
   {'date': new Date(2017,1,2), 'value': 3117},
];

// Generate a values index using the date time value
// saves searching through values for each member of data
var indexes = values.map(obj => +obj.date);
// Generate merged array
var merged = data.map(obj => {
  var index = indexes.indexOf(+obj.date); 
  return {date: obj.date, value: index > -1? values[index].value : obj.value};
});

console.log(merged)

Если у каждой даты будет только одно совпадение, вы можете дополнительно оптимизировать, удалив сопоставленные индексы, когда они сопоставлены, чтобы последующие поиски были (возможно, незаметно) быстрее.

2
RobG 30 Авг 2017 в 00:56

Думаю, использование хэш-набора было бы одним из самых быстрых способов https://codepen.io/TimCodes/pen/brQvbo?editors=0012

var masterListArr = [ { 'date' : new Date(), 'value' : 2 } , {'date' : new Date(2013, 13, 1), 'value' : 0}]
var secondListArr = [ { 'date' : new Date(), 'value' : null } , {'date' : new Date(2014, 13, 1), 'value' : null}]

var masterListHash = masterListArr.reduce(function(acc, cur, i) {
  acc[cur['date'].getTime()] = cur['value'] ;
  return acc;
}, {});


var mergedList = secondListArr.map(dateObj => {
   var dateKey = dateObj.date.getTime()
   if(masterListHash.hasOwnProperty(dateKey)){
        dateObj.value = masterListHash[dateKey]
   }
   return dateObj
})
0
TimCodes 30 Авг 2017 в 00:39

Хороший вопрос Я бы использовал метод reduce в главном списке, чтобы увидеть, содержит ли другой список совпадающую дату - если это так, объединить два объекта и перенести в новый массив, если не просто вытолкнуть объект из основного списка. Имейте в виду, это использует es6 - если es6 недоступен в среде, в которой вы используете, lodash имеет метод reduce и assign

const masterList = [/* ... */];
const otherArray = [/* ... */];

const mergedArray = masterList.reduce((a, b) => {
  const match = otherArray.filter(({ date }) => date.getTime() === b.date.getTime());
  if(match) {
    a.push(Object.assign(b, match));
  } else {
    a.push(b);
  }

  return a;
}, []);
0
pizza-r0b 30 Авг 2017 в 00:19