Как объединить два пересекающихся массива через es6 - PullRequest
0 голосов
/ 19 февраля 2020

У меня есть два массива, которые имеют свойства: minValue, maxValue, avgValue. Я хотел бы написать очень чистый подход к определению того, какие объекты соответствуют (displayName) в массиве, а затем присвоить значения нового массива старому (minPrice, maxPrice, avgPrice).

У меня есть это код до сих пор

export interface Player {
    displayName: string;
    MinPrice: number;
    MaxPrice: number;
    AvgPrice: number;}

export const MERGE_PLAYER_STATS = (playerStat: Player[], auctionStat: Player[]): any => {
      const reducer = (playerStat, auctionStat) => {
        playerStat.MinPrice = auctionStat.minPrice,
        playerStat.MaxPrice = auctionStat.maxPrice,
        playerStat.AvgPrice = auctionStat.avgPrice,
        playerStat.Team = auctionStat.team;
     }
      return reducer(playerStat, auctionStat =>
        filter(auctionStat, playerStat => auctionStat.displayName.includes(playerStat.displayName)));
}


Input: two different set of player arrays that have common display Names.  
playerStat: [] = [];
auctionStat: [] = [];

playerStat.push( {
displayName: "Josh Allen",
minPrice: "",
maxPrice: "",
avgPrice: ""
}, 
{
displayName: "No One",
minPrice: "",
maxPrice: "",
avgPrice: ""
});

auctionStat.push( {
displayName: "Josh Allen",
minPrice: 1,
maxPrice: 2,
avgPrice: 1
}, 
{
displayName: "No One 2",
minPrice: 1,
maxPrice: 1,
avgPrice: 2
});

Выходные данные должны содержать только статистику Jo sh Аллена, которая обновляется с пустых значений до 1,2,1 соответственно.

Пожалуйста, дайте мне знать, каков ваш чистый подход это. К вашему сведению, этот код не возвращает то, что я хочу.

Ответы [ 3 ]

0 голосов
/ 19 февраля 2020
playerStat.forEach((initItem) => {
  let result = auctionStat.filter((item) => (
    initItem.displayName === item.displayName 
  ))
  // let me suppose the same displayName only has one
  result.length && Object.assign(initItem, result[0])
})

0 голосов
/ 19 февраля 2020

Простой подход состоит в том, чтобы просто написать функцию отображения, которая копирует новые объекты на основе соответствующих ключей.

При заданном интерфейсе:

interface MyInterface {
  key: string;
  value: number;
}

И двух массивах:

const existingArray: MyInterface[] = [
  { key: 'a', value: 1 },
  { key: 'b', value: 2 },
  { key: 'c', value: 3 }
];

const newArray: MyInterface[] = [
  { key: 'b', value: 20 },
  { key: 'c', value: 30 },
  { key: 'd', value: 40 }
];

Ожидаемый результат

Я хочу обновить existingArray значениями newArray, где ключи совпадают.

  • Если значение не найдено в newArray, существующий элемент остается неизменным.
  • Если в newArray найдено новое значение, оно не объединяется в в oldArray
  • Все значения свойств должны быть перезаписаны

Мой ожидаемый результат:

const expected = [
  { key: 'a', value: 1 },
  { key: 'b', value: 20 },
  { key: 'c', value: 30 }
];

Solution

Я бы достиг этого с помощью этой функции слияния. Это просто карта массива javascript:

private merge<T>(existing: T[], updated: T[], getKey: (t: T) => string): T[] {
  // start with the existing array items
  return existing.map(item => {
    // get the key using the callback
    const key: string = getKey(item);
    // find the matching item by key in the updated array
    const matching: T = updated.find(x => getKey(x) === key);
    if (matching) {
      // if a matching item exists, copy the property values to the existing item
      Object.assign(item, matching);
    }
    return item;
  });
}

Я сделал ее обобщенной c, чтобы вы могли использовать ее с любым типом. Все, что вам нужно сделать, это предоставить 2 массива и обратный вызов для определения ключа.

Я бы использовал его для создания объединенного массива следующим образом:

const merged = this.merge(existingArray, newArray, x => x.key);

DEMO: https://stackblitz.com/edit/angular-nn8hit

Слово предупреждения

Это не будет хорошо масштабироваться с очень большими массивами. Если вы используете большие массивы, я бы оптимизировал, создав индексы типа Map<string, T>, чтобы фиксировать число циклов. Эта реализация выходит за рамки этого вопроса.

Редактировать:

Если вы хотите обновить только определенные значения c, вы можете передать обратный вызов обновления:

private merge<T>(existing: T[], updated: T[], getKey: (t: T) => string, 
  update: (item, matching) => void
): T[] {
  return existing.map(item => {
    const key: string = getKey(item);
    const matching: T = updated.find(x => getKey(x) === key);
    if (matching) {
      update(item, matching);
    }
    return item;
  });
}

И назовите это так:

const merged = this.merge(existingArray, newArray, x => x.key, 
  (item, matching) => item.value = matching.value);
0 голосов
/ 19 февраля 2020

Использовать Object.assign ()

Пример: oldArray = Object.assign (oldArray, newArray)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...