简体   繁体   English

分组,然后过滤

[英]Group by and then filter

I have below Object with me. 我下面有对象。

car = [{
    Acc: "X1",
    primary: true,
    Name: "Park Street",
    Date: "2018/01/01"
},{
    Acc: "X1",
    primary: false,
    Name: "Park Street 2",
    Date: "2018/03/01"
},{
    Acc: "X2",
    primary: false,
    Name: "Park Street 3",
    Date: "2018/01/01"
},{
    Acc: "X2",
    primary: false,
    Name: "Park Street 4",
    Date: "2018/05/01"
}];

I have to get only one element from each group of "Acc". 我必须从“ Acc”的每个组中仅获取一个元素。 One element for each of Acc:"X1" and Acc:"X2". Acc:“ X1”和Acc:“ X2”中的每一个元素。 Logic to find that should be if primary: true, then select that element from the group else pick the one having latest Date: value. 逻辑上找到应该是primary:true的逻辑,然后从组中选择该元素,否则选择具有最新Date:值的元素。

I do understand this requirement can be achievable using underscore js but I am new in this and can't figure out the relevant way. 我确实知道使用下划线js可以实现此要求,但我是新手,无法弄清楚相关方法。

Can someone please help me here? 有人可以在这里帮我吗?

One way to do this, is first group by Acc , and then within the group sort by primary & Date descending, and then just pick the first of each group. 一种方法是,首先按Acc分组,然后在组中按降序对primaryDate排序,然后仅选择每个组中的第一个。

eg. 例如。

 const car = [{ Acc: "X1", primary: true, Name: "Park Street", Date: "2018/01/01" },{ Acc: "X1", primary: false, Name: "Park Street 2", Date: "2018/03/01" },{ Acc: "X2", primary: false, Name: "Park Street 3", Date: "2018/01/01" },{ Acc: "X2", primary: false, Name: "Park Street 4", Date: "2018/05/01" }]; //lets group const grouped = car.reduce((a, v) => { if (!a[v.Acc]) a[v.Acc] = []; a[v.Acc].push(v); return a; }, {}); //now for each group sort by primary, and then Date const result = Object.values(grouped).map((g) => { g.sort((a, b) => b.primary - a.primary || b.Date.localeCompare(a.Date)); return g[0]; //now sorted, pick first. }); console.log(result); 

Another more efficient way, might be just to keep track of the best inside an object literal.. 另一种更有效的方法可能只是跟踪对象文字中的最佳内容。

eg.. 例如..

 const car = [{ Acc: "X1", primary: true, Name: "Park Street", Date: "2018/01/01" },{ Acc: "X1", primary: false, Name: "Park Street 2", Date: "2018/03/01" },{ Acc: "X2", primary: false, Name: "Park Street 3", Date: "2018/01/01" },{ Acc: "X2", primary: false, Name: "Park Street 4", Date: "2018/05/01" }]; const best = {}; car.forEach((c) => { const b = best[c.Acc] = best[c.Acc] || c; if (b.primary) return; if (c.Date.localeCompare(best.Date) < 0) best[c.Acc] = c; }); console.log(Object.values(best)); 

Since you have mentioned Underscore, I understand you can use external libraries. 由于您已经提到了Underscore,因此我了解您可以使用外部库。 This is the same approach as @Keith did, but using Lodash instead. 这与@Keith相同,但使用Lodash

Also, this should work with all browsers. 另外,这应该适用于所有浏览器。

 var car = [{ Acc: "X1", primary: true, Name: "Park Street", Date: "2018/01/01" },{ Acc: "X1", primary: false, Name: "Park Street 2", Date: "2018/03/01" },{ Acc: "X2", primary: false, Name: "Park Street 3", Date: "2018/01/01" },{ Acc: "X2", primary: false, Name: "Park Street 4", Date: "2018/05/01" }]; var sorted = _.orderBy(car, ['primary', 'Date'], ['desc', 'desc']); var groupedSorted = _.groupBy(sorted, 'Acc'); var result = _.flatMap(groupedSorted, function(o) { return o[0]; }); console.log(result); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script> 

if primary: true, then select that element from the group else pick the one having latest Date: value 如果primary:true,则从组中选择该元素,否则选择具有最新Date:值的元素

As per the above statement there is only one primary:true in each group ( X1 or X2 ). 根据以上声明,每个组( X1X2 )中只有一个primary:true If my understanding is correct you can try below code : 如果我的理解是正确的,您可以尝试以下代码

 // Input object var car = [{ Acc: "X1", primary: true, Name: "Park Street", Date: "2018/01/01" }, { Acc: "X1", primary: false, Name: "Park Street 2", Date: "2018/03/01" }, { Acc: "X2", primary: false, Name: "Park Street 3", Date: "2018/01/01" }, { Acc: "X2", primary: false, Name: "Park Street 4", Date: "2018/05/01" }]; // fetch the primary:true objects from the Input array. var primaryTrueArray = car.filter(obj => { if (obj.primary === true) { return obj; } }); // filtered out the primary:true objects from the Input array based on the primaryTrueArray.Hence, we will get all primary:false. var filteredOutPrimaryTrue = car.filter(obj => primaryTrueArray.filter(item => item.Acc != obj.Acc)); // Fetch the latest date from the group who has primary:false from the filteredOutPrimaryTrue. var latestDateFromGroup = filteredOutPrimaryTrue.sort(function(a,b){ if (a.Date < b.Date) return 1; else if (a.Date == b.Date) return 0; else return -1; }); // Concatenate both the arrays "primaryTrueArray & latestDateFromGroup" into single one. var finalResult = primaryTrueArray.concat([latestDateFromGroup[0]]); // Desired output. console.log(finalResult); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM