简体   繁体   English

对对象数组进行排序并取 N 个元素

[英]Sort an array of Objects and take N elements

in a NodeJS service I have an array with objects that have these properties:在 NodeJS 服务中,我有一个包含具有以下属性的对象的数组:

  • batchType: string批处理类型:字符串
  • batchId: string (is a hash) batchId:字符串(是一个散列)
  • transactionId: string (it's a hash) transactionId:字符串(它是一个哈希值)

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 个项目,但要遵守某些规则:

  1. At least get 1 item from each type of batch至少从每种类型的批次中获得 1 个项目
  2. At least get 1 item for each batchId每个batchId至少获得1个项目
  3. Sometimes the array could have only one type of batch有时数组可能只有一种类型的批处理

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.这个想法是按batchTypebatchId进行分组,并将此问题视为循环联合。 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:您可以分步骤执行此操作:

  • first add unique batchType elements (this meets the first criterion)首先添加唯一的 batchType 元素(这符合第一个标准)
  • then add unique batchId elements (this meets the second criterion)然后添加唯一的 batchId 元素(这符合第二个标准)
  • fill the array with remaining elements if there's still some space left (to go up to N elements)如果还有剩余空间,则用剩余的元素填充数组(最多 N 个元素)

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,你可以使用_.groupBybatchItembatchId对数组进行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.

相关问题 通过对象数组中的键获取元素 - Take elements by key in objects array jQuery-获取对象数组,然后根据数据集进行排序 - jQuery - Take array of objects, then sort based on a dataset 如何将具有n个元素的2个数组合并为具有n个对象的1个数组? - How to merge 2 arrays with n elements into 1 array with n objects? 随机获取n个元素数组,并将其插入指定的元素中 - Take a random n number array of elements and insert them in a specified element 如何使用angularjs从数组中随机取n个元素? - How to take random n elements from array using angularjs? 获取对象数组并按字母顺序排序为较小的数组 - Take array of objects and sort into smaller arrays sorted alphabetically 具有n个巨大对象元素的数组的排序速度是否比具有n个微小对象元素的数组的排序慢? - Does an array with n huge object elements sort slower that an array with n tiny object elements? 在javascript中对n维对象数组进行排序 - Sort through array of n-dimensional objects in javascript 如何根据数组字段中元素的出现次数对两个对象进行“排序”? - How to 'sort' two objects based on number of occurrences of elements in an array field? 根据频率对对象数组进行排序,但保留重复的元素 - Sort an array of objects based on frequency but keep repeated elements
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM