#javascript #arrays
#язык JavaScript #массивы #уменьшить
Вопрос:
Мне нужно решить следующую проблему с помощью функции, которая принимает массив объектов в качестве аргумента и решает все три случая. Учитывая массив объектов, как мне сгруппировать их в подмассивы на основе нескольких условий? Я ищу ошибки в платежной системе и хочу получить массив дублированных транзакций (отсортированных по времени транзакции по возрастанию).
Транзакции считаются дубликатами, если: производитель, сумма, категория точно совпадают, а время между транзакциями составляет менее 45 секунд.
Я ищу решение ES6, и я уверен, что оно будет включать метод .reduce.
Я попытался поработать над этим, выполнив команду reduce, которая дает мне объект, основанный на ключе производителя, и это не тот результат, которого я хотел бы достичь, так как мне нужны поддиапазоны вместо объектов, и мне нужно больше условий, чем просто производитель.
let groupedArr = data.reduce((accumulator, currentValue) =gt; { accumulator[currentValue.manufacturer] = [...accumulator[currentValue.manufacturer] || [], currentValue]; return accumulator; }, {});
Случай 1:
вход:
const data = [{ id: 3, manufacturer: 'audi', amount: 40, category: 'leasing', transaction: '2020-03-02T10:34:30.000Z' }, { id: 4, manufacturer: 'audi', amount: 40, category: 'leasing', transaction: '2020-03-02T10:34:38.000Z' }, { id: 1, manufacturer: 'mercedes', amount: 20, category: 'leasing', transaction: '2020-03-05T12:00:00.000Z' }, { id: 7, manufacturer: 'audi', amount: 40, category: 'leasing', transaction: '2020-03-20T11:00:00.000Z' }, { id: 6, manufacturer: 'mercedes', amount: 20, category: 'leasing', transaction: '2020-03-05T12:00:44.000Z' }, { id: 2, manufacturer: 'volkswagen', amount: 2, category: 'credit', transaction: '2020-03-05T12:00:45.000Z' }, { id: 5, manufacturer: 'audi', amount: 40, category: 'leasing', transaction: '2020-03-02T10:35:17.000Z' }, ]
Ожидаемый результат:
[[{ id: 3, manufacturer: 'audi', amount: 40, category: 'leasing', transaction: '2020-03-02T10:34:30.000Z' }, { id: 4, manufacturer: 'audi', amount: 40, category: 'leasing', transaction: '2020-03-02T10:34:38.000Z' }, { id: 5, manufacturer: 'audi', amount: 40, category: 'leasing', transaction: '2020-03-02T10:35:17.000Z' }], [{ id: 1, manufacturer: 'mercedes', amount: 20, category: 'leasing', transaction: '2020-03-05T12:00:00.000Z' }, { id: 6, manufacturer: 'mercedes', amount: 20, category: 'leasing', transaction: '2020-03-05T12:00:44.000Z' }] ]
Case 2:
INPUT:
const data = [{ id: 2, manufacturer: 'audi', amount: 40, category: 'leasing', transaction: '2020-03-02T10:34:30.000Z' }, { id: 7, manufacturer: 'audi', amount: 40, category: 'leasing', transaction: '2020-03-20T11:00:00.000Z' }]
Ожидаемый результат:
[]
Пояснение: Более 45 секунд между транзакциями должны выводить пустой массив.
Случай 3:
вход:
const data = [{ id: 2, manufacturer: 'audi', amount: 40, category: 'leasing', transaction: '2020-03-02T10:34:30.000Z' }, { id: 1, manufacturer: 'audi', amount: 40, category: 'credit', transaction: '2020-03-02T10:34:40.000Z' }]
Ожидаемый результат:
[]
Пояснение: Менее 45 секунд, но категория другая, поэтому она не считается дубликатом.
Комментарии:
1. «нужно больше условий, чем просто производитель» — Тогда не используйте только ключ производителя в качестве имени свойства. «Мне нужны вложенные массивы вместо объектов» -Просто преобразуйте их после того, как вы сгруппировали записи.
2. Почему id=2 (volkswagen, кредит) не будет включен в выходные данные для случая 1? Смотрите мой ответ для случая 1, я не понимаю, почему вы хотите это исключить. Также, когда есть дубликат (в течение 40 секунд, какой из них сохраняется — тот, который был «раньше» по времени?). Пожалуйста, постарайтесь объяснить это и по возможности сделать свой вопрос немного яснее.
3. Будут ли дубликаты всегда иметь один и тот же идентификатор? (Так как здесь есть две записи для Audi с идентификатором=5, и они находятся в течение 40 секунд) — Плохая практика использовать один и тот же идентификатор дважды, но если это то, что означает дубликат, который также легко решить.
4. отлично, мой ответ должен дать вам то, чего вы сейчас ожидаете.
Ответ №1:
Случай 1:
function example1(initData, fieldsArr){ const output = data.reduce((aggObj, item) =gt; { const stringId = fieldsArr.map(key =gt; item[key]).join('_'); if (aggObj[stringId]){ aggObj[stringId].push(item); } else { aggObj[stringId] = [item]; } return aggObj; }, {}) const outputNoDups = Object.values(output).map(group =gt; { const sorted = group.sort((a,b) =gt; new Date(a.transaction) lt; new Date(b.transaction) ? -1 : 1); return sorted.filter((a, i) =gt; { if (i == 0) return true; if (a.amount == sorted[i - 1].amount amp;amp; new Date(a.transaction) - new Date(sorted[i - 1].transaction) lt;= 45000){ return true; } return false; }); }); return outputNoDups.filter(a =gt; a.length gt; 1); } console.log(example1(data, ['manufacturer', 'category']));
.as-console-wrapper { max-height: 100% !important; top: 0; }
lt;script id="initData"gt; const data = [{ id: 3, manufacturer: 'audi', amount: 40, category: 'leasing', transaction: '2020-03-02T10:34:30.000Z' }, { id: 4, manufacturer: 'audi', amount: 40, category: 'leasing', transaction: '2020-03-02T10:34:38.000Z' }, { id: 1, manufacturer: 'mercedes', amount: 20, category: 'leasing', transaction: '2020-03-05T12:00:00.000Z' }, { id: 7, manufacturer: 'audi', amount: 40, category: 'leasing', transaction: '2020-03-20T11:00:00.000Z' }, { id: 6, manufacturer: 'mercedes', amount: 20, category: 'leasing', transaction: '2020-03-05T12:00:44.000Z' }, { id: 2, manufacturer: 'volkswagen', amount: 2, category: 'credit', transaction: '2020-03-05T12:00:45.000Z' }, { id: 5, manufacturer: 'audi', amount: 40, category: 'leasing', transaction: '2020-03-02T10:35:17.000Z' }, ]; lt;/scriptgt;
OUTPUT (Case 1):
[ [ { "id": 3, "manufacturer": "audi", "amount": 40, "category": "leasing", "transaction": "2020-03-02T10:34:30.000Z" }, { "id": 4, "manufacturer": "audi", "amount": 40, "category": "leasing", "transaction": "2020-03-02T10:34:38.000Z" }, { "id": 5, "manufacturer": "audi", "amount": 40, "category": "leasing", "transaction": "2020-03-02T10:35:17.000Z" } ], [ { "id": 1, "manufacturer": "mercedes", "amount": 20, "category": "leasing", "transaction": "2020-03-05T12:00:00.000Z" }, { "id": 6, "manufacturer": "mercedes", "amount": 20, "category": "leasing", "transaction": "2020-03-05T12:00:44.000Z" } ] ]
Случай 2:
function example1(initData, fieldsArr){ const output = data.reduce((aggObj, item) =gt; { const stringId = fieldsArr.map(key =gt; item[key]).join('_'); if (aggObj[stringId]){ aggObj[stringId].push(item); } else { aggObj[stringId] = [item]; } return aggObj; }, {}) const outputNoDups = Object.values(output).map(group =gt; { const sorted = group.sort((a,b) =gt; new Date(a.transaction) lt; new Date(b.transaction) ? -1 : 1); return sorted.filter((a, i) =gt; { if (i == 0) return true; if (a.amount == sorted[i - 1].amount amp;amp; new Date(a.transaction) - new Date(sorted[i - 1].transaction) lt;= 45000){ return true; } return false; }); }); return outputNoDups.filter(a =gt; a.length gt; 1); } console.log(example1(data, ['manufacturer', 'category']));
.as-console-wrapper { max-height: 100% !important; top: 0; }
lt;script id="initData"gt; const data = [{ id: 2, manufacturer: 'audi', amount: 40, category: 'leasing', transaction: '2020-03-02T10:34:30.000Z' }, { id: 7, manufacturer: 'audi', amount: 40, category: 'leasing', transaction: '2020-03-20T11:00:00.000Z' }] lt;/scriptgt;
Случай 3:
function example1(initData, fieldsArr){ const output = data.reduce((aggObj, item) =gt; { const stringId = fieldsArr.map(key =gt; item[key]).join('_'); if (aggObj[stringId]){ aggObj[stringId].push(item); } else { aggObj[stringId] = [item]; } return aggObj; }, {}) const outputNoDups = Object.values(output).map(group =gt; { const sorted = group.sort((a,b) =gt; new Date(a.transaction) lt; new Date(b.transaction) ? -1 : 1); return sorted.filter((a, i) =gt; { if (i == 0) return true; if (a.amount == sorted[i - 1].amount amp;amp; new Date(a.transaction) - new Date(sorted[i - 1].transaction) lt;= 45000){ return true; } return false; }); }); return outputNoDups.filter(a =gt; a.length gt; 1); } console.log(example1(data, ['manufacturer', 'category']));
.as-console-wrapper { max-height: 100% !important; top: 0; }
lt;script id="initData"gt; const data = [{ id: 2, manufacturer: 'audi', amount: 40, category: 'leasing', transaction: '2020-03-02T10:34:30.000Z' }, { id: 1, manufacturer: 'audi', amount: 40, category: 'credit', transaction: '2020-03-02T10:34:40.000Z' }] lt;/scriptgt;
Case 4 (an edge case you hadn’t considered — time is less than 45 but amount is different):
function example1(initData, fieldsArr){ const output = data.reduce((aggObj, item) =gt; { const stringId = fieldsArr.map(key =gt; item[key]).join('_'); if (aggObj[stringId]){ aggObj[stringId].push(item); } else { aggObj[stringId] = [item]; } return aggObj; }, {}) const outputNoDups = Object.values(output).map(group =gt; { const sorted = group.sort((a,b) =gt; new Date(a.transaction) lt; new Date(b.transaction) ? -1 : 1); return sorted.filter((a, i) =gt; { if (i == 0) return true; if (a.amount == sorted[i - 1].amount amp;amp; new Date(a.transaction) - new Date(sorted[i - 1].transaction) lt;= 45000){ return true; } return false; }); }); return outputNoDups.filter(a =gt; a.length gt; 1); } console.log(example1(data, ['manufacturer', 'category']));
.as-console-wrapper { max-height: 100% !important; top: 0; }
lt;script id="initData"gt; const data = [{ id: 2, manufacturer: 'audi', amount: 40, category: 'leasing', transaction: '2020-03-02T10:34:30.000Z' }, { id: 1, manufacturer: 'audi', amount: 30, category: 'leasing', transaction: '2020-03-02T10:34:40.000Z' }] lt;/scriptgt;
Комментарии:
1. Я думаю, что ваш вывод непоследователен и неясен. Пожалуйста, уточните, и я легко смогу это решить. Почему id=2 (volkswagen, кредит) не будет включен в выходные данные для случая 1? Я не понимаю, почему вы хотите это исключить. Также, когда есть дубликат (в течение 40 секунд, какой из них сохраняется — тот, который был «раньше» по времени?). Пожалуйста, постарайтесь объяснить это и по возможности сделать свой вопрос немного яснее.
2. Когда в указанных условиях выполняется только одна транзакция (в данном случае у Volkswagen нет подобной транзакции), она должна быть исключена из массива дубликатов (который по определению должен включать 2 или более транзакций).
3. Все транзакции должны быть сохранены, если разница во времени между последней и последующей составляет менее 45 секунд.
4. Пожалуйста, также проверьте всю метку даты. Иногда дни месяца отличаются, поэтому объект не следует включать в массив.
5. Отлично работает в случае 1, но один и тот же код должен работать также для случая 2 и случая 3. Прямо сейчас он выдает одинаковый результат для всех трех случаев, но в случае 2 и 3 должен выводить пустой массив.