Javascript - группировка и сортировка объектов - PullRequest
1 голос
/ 13 апреля 2019

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

Я ищу КАРТУ, УМЕНЬШЕНИЕ и ФИЛЬТРЫ, но не могу найти хороший способ.

Цели были:

  1. Поиск дублирующих транзакций.
  2. Групповое сходство
  3. Сортировать результаты

Инструкция : Иногда, когда с клиента взимается плата, создается дублирующая транзакция. Нам нужно найти эти транзакции, чтобы с ними можно было справиться. Все в транзакции должно быть идентичным, за исключением идентификатора транзакции и времени, когда она произошла, поскольку задержка может быть до минуты.

findDuplicateTransactions (сделки)

Найти все транзакции, которые имеют одинаковые sourceAccount, targetAccount, категорию, сумму и разница во времени между каждой последовательной транзакцией составляет менее 1 минуты.

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

список транзакций (транзакция []) выход список всех дубликатов групп транзакций, упорядоченный по возрастанию времени (Transaction [] []) Группы должны быть отсортированы в порядке возрастания первой транзакции в группе. пример Ввод:

[
  {
    id: 3,
    sourceAccount: 'A',
    targetAccount: 'B',
    amount: 100,
    category: 'eating_out',
    time: '2018-03-02T10:34:30.000Z'
  },
  {
    id: 1,
    sourceAccount: 'A',
    targetAccount: 'B',
    amount: 100,
    category: 'eating_out',
    time: '2018-03-02T10:33:00.000Z'
  },
  {
    id: 6,
    sourceAccount: 'A',
    targetAccount: 'C',
    amount: 250,
    category: 'other',
    time: '2018-03-02T10:33:05.000Z'
  },
  {
    id: 4,
    sourceAccount: 'A',
    targetAccount: 'B',
    amount: 100,
    category: 'eating_out',
    time: '2018-03-02T10:36:00.000Z'
  },
  {
    id: 2,
    sourceAccount: 'A',
    targetAccount: 'B',
    amount: 100,
    category: 'eating_out',
    time: '2018-03-02T10:33:50.000Z'
  },
  {
    id: 5,
    sourceAccount: 'A',
    targetAccount: 'C',
    amount: 250,
    category: 'other',
    time: '2018-03-02T10:33:00.000Z'
  }
];

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

[
  [
    {
      id: 1,
      sourceAccount: "A",
      targetAccount: "B",
      amount: 100,
      category: "eating_out",
      time: "2018-03-02T10:33:00.000Z"
    },
    {
      id: 2,
      sourceAccount: "A",
      targetAccount: "B",
      amount: 100,
      category: "eating_out",
      time: "2018-03-02T10:33:50.000Z"
    },
    {
      id: 3,
      sourceAccount: "A",
      targetAccount: "B",
      amount: 100,
      category: "eating_out",
      time: "2018-03-02T10:34:30.000Z"
    }
  ],
  [
    {
      id: 5,
      sourceAccount: "A",
      targetAccount: "C",
      amount: 250,
      category: "other",
      time: "2018-03-02T10:33:00.000Z"
    },
    {
      id: 6,
      sourceAccount: "A",
      targetAccount: "C",
      amount: 250,
      category: "other",
      time: "2018-03-02T10:33:05.000Z"
    }
  ]
];

Это мой код, но он мне не понравился. Есть какой-нибудь хороший способ сделать?

function findDuplicateTransactions (transactions = []) {
    var result = [];

    console.info("total itens :" + transactions.length);

      //sort
      transactions = transactions.sort((a,b)=> a.time.localeCompare(b.time))

      //remove itens not duplicated
      result = removeItens(transactions);


      //group
      result = groupBy(result, function(item){
          return [item.sourceAccount, item.targetAccount, item.amount, item.category];
      });

  console.info(result);

      //remove UniqueElements
      result = removeUniqueElements(result);



      return result;
  }

  function removeUniqueElements(array){
      var filtered = array.filter(function(value, index, arr){
          return value.length >= 2;
      });

      return filtered;
  }

  function removeItens(array){
      var itensToBeRemoved = [];
      for (var index = 0; index < array.length; index++) {
          const element1 = array[index];
          var cont = 0;

          console.info("============== looking for: " + element1.id);

          for (var index2 = 0; index2 < array.length; index2++) {
              const element2 = array[index2];

              if(element1.id != element2.id){


                var date1 = new Date(element1.time);
                var date2 = new Date(element2.time);

                var timeDiff = Math.abs(date2.getTime() - date1.getTime());

                console.info("comparing :" + element1.id + "<->" + element2.id + " diff: " + timeDiff);


                if( timeDiff < 60000) {
                    //keep it - is similar
                    console.info("find one duplicated: " + element2.id);
                    break;
                }else{
                    cont++;
                }
              }
          }

          //console.info("cont: " + cont)

          if(cont == array.length-1){
            //array.splice(index, 1);
            console.info("possible duplicated: " + element1.id);
            itensToBeRemoved.push(element1.id);
          }
      }

      var filtered = [];

      for(var i=0; i<itensToBeRemoved.length; i++){
          console.info("remove item: " + itensToBeRemoved[i]);
          array = arrayRemove(array, itensToBeRemoved[i]);
      }

    return array;
  }

function arrayRemove(arr, value) {
   return arr.filter(function(ele){
       console.info("watching: " + ele.id);
       console.info("index: " + value);
       return ele.id != value;
   });
}

  function groupBy( array , f ){
      var lists = {};
      array.forEach( function( o ){
          var list = JSON.stringify( f(o) );
          lists[list] = lists[list] || [];
          lists[list].push( o );  
      });
      return Object.keys(lists).map( function( list ){
          return lists[list]; 
      })
  }

Ответы [ 2 ]

3 голосов
/ 13 апреля 2019

Вы можете отсортировать массив заранее и уменьшить его, найдя группу с той же категорией.

var data = [{ id: 3, sourceAccount: 'A', targetAccount: 'B', amount: 100, category: 'eating_out', time: '2018-03-02T10:34:30.000Z' }, { id: 1, sourceAccount: 'A', targetAccount: 'B', amount: 100, category: 'eating_out', time: '2018-03-02T10:33:00.000Z' }, { id: 6, sourceAccount: 'A', targetAccount: 'C', amount: 250, category: 'other', time: '2018-03-02T10:33:05.000Z' }, { id: 4, sourceAccount: 'A', targetAccount: 'B', amount: 100, category: 'eating_out', time: '2018-03-02T10:36:00.000Z' }, { id: 2, sourceAccount: 'A', targetAccount: 'B', amount: 100, category: 'eating_out', time: '2018-03-02T10:33:50.000Z' }, { id: 5, sourceAccount: 'A', targetAccount: 'C', amount: 250, category: 'other', time: '2018-03-02T10:33:00.000Z' }],
    result = data
        .sort(({ time: a }, { time: b }) => a.localeCompare(b))
        .reduce((r, o) => {
            var temp = r.find(([{ category }]) => category === o.category);
            if (!temp) r.push(temp = []);
            temp.push(o);
            return r;
        }, []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

С хеш-таблицей.

const delta = (t1, t2) => Math.abs(new Date(t1) - new Date(t2));

var data = [{ id: 3, sourceAccount: 'A', targetAccount: 'B', amount: 100, category: 'eating_out', time: '2018-03-02T10:34:30.000Z' }, { id: 1, sourceAccount: 'A', targetAccount: 'B', amount: 100, category: 'eating_out', time: '2018-03-02T10:33:00.000Z' }, { id: 6, sourceAccount: 'A', targetAccount: 'C', amount: 250, category: 'other', time: '2018-03-02T10:33:05.000Z' }, { id: 4, sourceAccount: 'A', targetAccount: 'B', amount: 100, category: 'eating_out', time: '2018-03-02T10:36:00.000Z' }, { id: 2, sourceAccount: 'A', targetAccount: 'B', amount: 100, category: 'eating_out', time: '2018-03-02T10:33:50.000Z' }, { id: 5, sourceAccount: 'A', targetAccount: 'C', amount: 250, category: 'other', time: '2018-03-02T10:33:00.000Z' }],
    keys = ['sourceAccount', 'targetAccount', 'amount', 'category'],
    result = Object.values(data
        .sort(({ time: a }, { time: b }) => a.localeCompare(b))
        .filter((o, i, a) => {
            while (a[--i] && delta(o.time, a[i].time) < 60000) {
                if (keys.every(k => o[k] === a[i][k])) return;
            }
            return true;
        })
        .reduce((r, o) => ((r[o.category] = r[o.category] || []).push(o), r), {})
    );

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
0 голосов
/ 13 апреля 2019

Вы можете сначала отсортировать по времени, а затем уменьшить

let data =  [{id: 3,sourceAccount: 'A',targetAccount: 'B',amount: 100,category: 'eating_out',time: '2018-03-02T10:34:30.000Z'},{id: 1,sourceAccount: 'A',targetAccount: 'B',amount: 100,category: 'eating_out',time: '2018-03-02T10:33:00.000Z'},
{id: 6,sourceAccount: 'A',targetAccount: 'C',amount: 250,category: 'other',time: '2018-03-02T10:33:05.000Z'},
{id: 4,sourceAccount: 'A',targetAccount: 'B',amount: 100,category: 'eating_out',time: '2018-03-02T10:36:00.000Z'},
{id: 2,sourceAccount: 'A',targetAccount: 'B',amount: 100,category: 'eating_out',time: '2018-03-02T10:33:50.000Z'},{id: 5,sourceAccount: 'A',targetAccount: 'C',amount: 250,category: 'other',time: '2018-03-02T10:33:00.000Z'}];

let sortedData = data.sort((a,b)=> a.time.localeCompare(b.time))

let keyTrack = sortedData[0].sourceAccount + sortedData[0].targetAccount
let temp = []
let final = sortedData.reduce((op,inp) => {
  let key = inp.sourceAccount + inp.targetAccount
  if(keyTrack !== key){
    keyTrack = key
    op.push(temp)
    temp = []
  }
  temp.push(inp)
  return op
},[])

if(temp.length){
  final.push(temp)
}

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