[英]Sort an array of Objects and take N elements
in a NodeJS service I have an array with objects that have these properties:在 NodeJS 服务中,我有一个包含具有以下属性的对象的数组:
This array stores all transactions of different types of batches.该数组存储不同类型批次的所有交易。
Basically what I need is to be able to get N items from the array, but respecting certain rules:基本上我需要的是能够从数组中获取 N 个项目,但要遵守某些规则:
This is an example of the array:这是数组的示例:
let batchTransactionsArray = [
{ batchType: 'type1', batchId: '123', transactionId: 'ffasf23' },
{ batchType: 'type1', batchId: '312', transactionId: '423' },
{ batchType: 'type1', batchId: '123', transactionId: '534' },
{ batchType: 'type1', batchId: '312', transactionId: '86' },
{ batchType: 'type2', batchId: '111', transactionId: '97' },
{ batchType: 'type1', batchId: '312', transactionId: '1945' },
{ batchType: 'type1', batchId: '123', transactionId: '79' },
{ batchType: 'type1', batchId: '312', transactionId: '79' },
{ batchType: 'type3', batchId: '425', transactionId: '1555645' },
{ batchType: 'type1', batchId: '123', transactionId: 'fg5' },
{ batchType: 'type1', batchId: '123', transactionId: 'jkh5' },
{ batchType: 'type1', batchId: '312', transactionId: '53j' },
{ batchType: 'type1', batchId: '111', transactionId: '4545' },
{ batchType: 'type2', batchId: '111', transactionId: '534l' },
{ batchType: 'type1', batchId: '111', transactionId: 'jkg435' },
{ batchType: 'type1', batchId: '111', transactionId: 'gfxg23' },
{ batchType: 'type1', batchId: '111', transactionId: '7asdt' },
{ batchType: 'type1', batchId: '222', transactionId: 'jdsa7' },
{ batchType: 'type3', batchId: '663', transactionId: '12423445' },
{ batchType: 'type1', batchId: '111', transactionId: '89saf6' },
{ batchType: 'type1', batchId: '111', transactionId: '12h3g' },
{ batchType: 'type1', batchId: '111', transactionId: '4h3k2hj' },
{ batchType: 'type3', batchId: '663', transactionId: '145' }
];
And an example of the output I need is (if I want 5 transactions from the array):我需要的输出示例是(如果我想要数组中的 5 个事务):
[{ batchType: 'type1', batchId: '123', transactionId: '534' },
{ batchType: 'type1', batchId: '312', transactionId: '86' },
{ batchType: 'type2', batchId: '111', transactionId: '97' },
{ batchType: 'type2', batchId: '111', transactionId: '534l' },
{ batchType: 'type3', batchId: '663', transactionId: '145' }
]
The criteria for sorting transactionIds would be random, there is no specific order to meet.对 transactionId 进行排序的标准将是随机的,没有要满足的特定顺序。
I was trying some lodash functions like groupBy and sortBy but no luck yet.我正在尝试一些 lodash 函数,如 groupBy 和 sortBy,但还没有运气。
Here is a jsfiddle were I was playing with this: https://jsfiddle.net/20jh3ze7/这是我正在玩的 jsfiddle: https ://jsfiddle.net/20jh3ze7/
I really appreciate suggestions.我非常感谢建议。
You could do something like this using lodash:你可以使用 lodash 做这样的事情:
let data = [ { batchType: 'type1', batchId: '123', transactionId: 'ffasf23' }, { batchType: 'type1', batchId: '312', transactionId: '423' }, { batchType: 'type1', batchId: '123', transactionId: '534' }, { batchType: 'type1', batchId: '312', transactionId: '86' }, { batchType: 'type2', batchId: '111', transactionId: '97' }, { batchType: 'type1', batchId: '312', transactionId: '1945' }, { batchType: 'type1', batchId: '123', transactionId: '79' }, { batchType: 'type1', batchId: '312', transactionId: '79' }, { batchType: 'type3', batchId: '425', transactionId: '1555645' }, { batchType: 'type1', batchId: '123', transactionId: 'fg5' }, { batchType: 'type1', batchId: '123', transactionId: 'jkh5' }, { batchType: 'type1', batchId: '312', transactionId: '53j' }, { batchType: 'type1', batchId: '111', transactionId: '4545' }, { batchType: 'type2', batchId: '111', transactionId: '534l' }, { batchType: 'type1', batchId: '111', transactionId: 'jkg435' }, { batchType: 'type1', batchId: '111', transactionId: 'gfxg23' }, { batchType: 'type1', batchId: '111', transactionId: '7asdt' }, { batchType: 'type1', batchId: '222', transactionId: 'jdsa7' }, { batchType: 'type3', batchId: '663', transactionId: '12423445' }, { batchType: 'type1', batchId: '111', transactionId: '89saf6' }, { batchType: 'type1', batchId: '111', transactionId: '12h3g' }, { batchType: 'type1', batchId: '111', transactionId: '4h3k2hj' }, { batchType: 'type3', batchId: '663', transactionId: '145' } ]; const customTake = (d, n) => { const roundRobinUnion = (arr) => { let res = [] while (_.flatten(arr).length) _.each(arr, x => x.length ? res.push(_.remove(x, (y, i) => i == 0)) : null) return _.flatten(res) } const groups = _(d) .orderBy(['batchType', 'batchId']) .groupBy('batchType') .mapValues(x => _.values(_.groupBy(x, 'batchId'))) .map(x => roundRobinUnion(x)) .value() return _.take(roundRobinUnion(groups), n) } console.log(customTake(data, 3)) console.log(customTake(data, 5)) console.log(customTake(data, 6)) console.log(customTake(data, 8))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
The idea is to group by both batchType
and batchId
and think about this issue as a round robin union.这个想法是按batchType
和batchId
进行分组,并将此问题视为循环联合。 You go through each array index and do an union of each element.您遍历每个数组索引并对每个元素进行联合。
If you care about the end sort order you can always do another orderBy
at the end etc.如果您关心结束排序顺序,您总是可以在最后执行另一个orderBy
等。
Here is a simple example of the roundRobinUnion
idea:这是roundRobinUnion
想法的一个简单示例:
const data = [ [1, 2, 3], [1], [5, 6] ] const roundRobinUnion = (arr) => { let res = [] while (_.flatten(arr).length) _.each(arr, x => x.length ? res.push(_.remove(x, (y, i) => i == 0)) : null) return _.flatten(res) } console.log(roundRobinUnion(data)) // [1,1,5,2,6,3]
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
You can do this in steps:您可以分步骤执行此操作:
To check for uniqueness, you can use a Set
.要检查唯一性,您可以使用Set
。 Since you said you're using lodash, you can use _.groupBy
to group your array by batchItem
and batchId
to get unique elements from each group.既然你说你正在使用 lodash,你可以使用_.groupBy
按batchItem
和batchId
对数组进行batchItem
,以从每个组中获取唯一元素。
let batchTransactionsArray = [ { batchType: 'type1', batchId: '123', transactionId: 'ffasf23' }, { batchType: 'type1', batchId: '312', transactionId: '423' }, { batchType: 'type1', batchId: '123', transactionId: '534' }, { batchType: 'type1', batchId: '312', transactionId: '86' }, { batchType: 'type2', batchId: '111', transactionId: '97' }, { batchType: 'type1', batchId: '312', transactionId: '1945' }, { batchType: 'type1', batchId: '123', transactionId: '79' }, { batchType: 'type1', batchId: '312', transactionId: '79' }, { batchType: 'type3', batchId: '425', transactionId: '1555645' }, { batchType: 'type1', batchId: '123', transactionId: 'fg5' }, { batchType: 'type1', batchId: '123', transactionId: 'jkh5' }, { batchType: 'type1', batchId: '312', transactionId: '53j' }, { batchType: 'type1', batchId: '111', transactionId: '4545' }, { batchType: 'type2', batchId: '111', transactionId: '534l' }, { batchType: 'type1', batchId: '111', transactionId: 'jkg435' }, { batchType: 'type1', batchId: '111', transactionId: 'gfxg23' }, { batchType: 'type1', batchId: '111', transactionId: '7asdt' }, { batchType: 'type1', batchId: '222', transactionId: 'jdsa7' }, { batchType: 'type3', batchId: '663', transactionId: '12423445' }, { batchType: 'type1', batchId: '111', transactionId: '89saf6' }, { batchType: 'type1', batchId: '111', transactionId: '12h3g' }, { batchType: 'type1', batchId: '111', transactionId: '4h3k2hj' }, { batchType: 'type3', batchId: '663', transactionId: '145' } ]; function getNItems(array, N = 5) { if (N >= array.length) return array; let batchTypeGroups = _.groupBy(array, e => e.batchType), res = new Set(), batchIds = new Set(); // add unique batchTypes for (let [batchType, elements] of Object.entries(batchTypeGroups)) { if (res.size === N) break; let d = elements.find(e => !batchIds.has(e.batchId)); if (d) { res.add(d); batchIds.add(d.batchId); } else { res.add(elements[0]); } } // add remaining unique batchIds let batchIdGroups = _.groupBy(array.filter(e => !batchIds.has(e.batchId)), e => e.batchId); for (let [batchId, elements] of Object.entries(batchIdGroups)) { if (res.size === N) break; res.add(elements[0]); } // add any remaining elements until we have N elements for (let e of array) { if (res.size === N) break; res.add(e); } return Array.from(res); } console.log(getNItems(batchTransactionsArray, 5));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
I think that for this type of problem we don't need extra dependencies.我认为对于此类问题,我们不需要额外的依赖项。
We can do it by plain javascript :)我们可以通过普通的 javascript 来完成:)
let batchTransactionsArray = [ { batchType: "type1", batchId: "123", transactionId: "ffasf23" }, { batchType: "type1", batchId: "312", transactionId: "423" }, { batchType: "type1", batchId: "123", transactionId: "534" }, { batchType: "type1", batchId: "312", transactionId: "86" }, { batchType: "type2", batchId: "111", transactionId: "97" }, { batchType: "type1", batchId: "312", transactionId: "1945" }, { batchType: "type1", batchId: "123", transactionId: "79" }, { batchType: "type1", batchId: "312", transactionId: "79" }, { batchType: "type3", batchId: "425", transactionId: "1555645" }, { batchType: "type1", batchId: "123", transactionId: "fg5" }, { batchType: "type1", batchId: "123", transactionId: "jkh5" }, { batchType: "type1", batchId: "312", transactionId: "53j" }, { batchType: "type1", batchId: "111", transactionId: "4545" }, { batchType: "type2", batchId: "111", transactionId: "534l" }, { batchType: "type1", batchId: "111", transactionId: "jkg435" }, { batchType: "type1", batchId: "111", transactionId: "gfxg23" }, { batchType: "type1", batchId: "111", transactionId: "7asdt" }, { batchType: "type1", batchId: "222", transactionId: "jdsa7" }, { batchType: "type3", batchId: "663", transactionId: "12423445" }, { batchType: "type1", batchId: "111", transactionId: "89saf6" }, { batchType: "type1", batchId: "111", transactionId: "12h3g" }, { batchType: "type1", batchId: "111", transactionId: "4h3k2hj" }, { batchType: "type3", batchId: "663", transactionId: "145" } ]; const getUniqueBatches = () => { const uniqueBatches = []; batchTransactionsArray.forEach(b => { const batchByType = uniqueBatches.find(findBatchByType(b.batchType)); const batchById = uniqueBatches.find(findBatchByBatchId(b.batchId)); if (!batchByType || !batchById) { uniqueBatches.push(b); } }); return uniqueBatches; }; const findBatchByType = batchType => { return batch => { return batch.batchType === batchType; }; }; const findBatchByBatchId = batchId => { return batch => { return batch.batchId === batchId; }; }; console.log(getUniqueBatches());
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.