Javascript удалить дубликаты в списке объектов, объединяющих некоторые свойства - PullRequest
0 голосов
/ 19 ноября 2018

У меня есть этот список:

const debts = [
  {
    amount: 10,
    debtor: "Mark",
    creditor: "John"
  },
  {
    amount: 20,
    debtor: "Mark",
    creditor: "John"
  },
  {
    amount: 10,
    debtor: "Mark",
    creditor: "Tom"
   }
];

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

const debts = [
  {
    amount: 30, // 10 + 20
    debtor: "Mark",
    creditor: "John"
  },
  {
    amount: 10,
    debtor: "Mark",
    creditor: "Tom"
   }
];

Можеткто-нибудь поможет мне?Спасибо

Ответы [ 3 ]

0 голосов
/ 19 ноября 2018

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

Наконец, используйте Object.values ​​, чтобы собрать все объекты.

let debts = [{amount: 10,debtor: "Mark",creditor: "John"},{amount: 20,debtor: "Mark",creditor: "John"},{amount: 10,debtor: "Mark",creditor: "Tom"}];

let result = Object.values(debts.reduce((a,c) => {
  let key = `${c.debtor}~~${c.creditor}`;
  if(a[key]) a[key].amount += c.amount;
  else a[key] = Object.assign({},c);
  return a;
}, {}));
console.log(result);
0 голосов
/ 19 ноября 2018

Если вы заинтересованы в решении с использованием Ramda, вот предложение:

const {
  pipe,
  mergeWithKey,
  map,
  reduce,
  values,
  groupBy,
  props,
  join
} = R;

const debts = [{
    amount: 10,
    debtor: "Mark",
    creditor: "John"
  },
  {
    amount: 20,
    debtor: "Mark",
    creditor: "John"
  },
  {
    amount: 10,
    debtor: "Mark",
    creditor: "Tom"
  }
];

const mergeAmount = mergeWithKey((key, left, right) => key === 'amount' ? left + right : left);
const groupKey = pipe(props(['debtor', 'creditor']), join(' ~> '));

const process =
  pipe(
    groupBy(groupKey),
    map(reduce(mergeAmount, {})),
    values);

console.log(process(debts));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>

Идея состоит в том, чтобы разделить процесс на три этапа:

  1. Группировать должников и кредиторов вместе
  2. Для каждой группы должников / кредиторов объединить сумму
  3. Извлечь каждую группу должников / кредиторов в массив

Шаг 1: groupBy (groupKey)

Шаг 1 получает исходный debts массив

{
    "Mark ~> John": [
        {
            amount: 10,
            creditor: "John",
            debtor: "Mark"
        },
        {
            amount: 20,
            creditor: "John",
            debtor: "Mark"
        }
    ],
    "Mark ~> Tom": [
        {
            amount: 10,
            creditor: "Tom",
            debtor: "Mark"
        }
    ]
}

Шаг 2: карта (уменьшение (mergeAmount, {}))

Шаг 2 получает выходные данныес шага 1

{
    "Mark ~> John": {
        amount: 30,
        creditor: "John",
        debtor: "Mark"
    },
    "Mark ~> Tom": {
        amount: 10,
        creditor: "Tom",
        debtor: "Mark"
    }
}

Шаг 3: значения

Шаг 3 получает выходные данные с шага 2

[
    {
        amount: 30,
        creditor: "John",
        debtor: "Mark"
    },
    {
        amount: 10,
        creditor: "Tom",
        debtor: "Mark"
    }
]
0 голосов
/ 19 ноября 2018

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

const debts = [
  {
    amount: 10,
    debtor: "Mark",
    creditor: "John"
  },
  {
    amount: 20,
    debtor: "Mark",
    creditor: "John"
  },
  {
    amount: 10,
    debtor: "Mark",
    creditor: "Tom"
  }
];

var result = []
debts.forEach((item) => {
  var existing = result.filter((resultItem, index) => {
    return resultItem.debtor === item.debtor && resultItem.creditor === item.creditor;
  });

  if (existing.length) {
    var existingIndex = result.indexOf(existing[0]);
    result[existingIndex].amount += item.amount;
  } else {
    result.push(item);
  }
})

console.log(result)
...