2017-04-25 78 views
2

我觉得可能有更好的解决方案,因为我在下面的例程(地图和排序)中重复代码。过滤器,地图,排序和concat

这是一个读取(1或null)和未读状态(0)的消息的任意列表。我在顶部显示未读消息,在底部读取消息,并应用一些排序和映射,然后在尾部连接两个结果。

var unread = data.filter(function(item){ 
    return item.Read == 0; 
}).map(function(item){ 
    return {Id: item.Id, First: item.First.toLowerCase(), Last: item.Last.toLowerCase()} 
}).sort(function(a, b){ 
    if (a.Last < b.Last) return -1; 
    if (a.Last > b.Last) return 1; 
    return 0; 
}); 

var read = data.filter(function(item){ 
    return item.Read == null || item.Read == 1; 
}).map(function(item){ // lowercase (first, last) and sort the list by last 
    return {Id: item.Id, First: item.First.toLowerCase(), Last: item.Last.toLowerCase()} 
}).sort(function(a, b){ 
    if (a.Last < b.Last) return -1; 
    if (a.Last > b.Last) return 1; 
    return 0; 
}); 

var finalData = unread.concat(read); 

编辑

var input = [ 
    {Id: 1, First: "John", Last: "B", Read:0}, 
    {Id: 1, First: "Jane", Last: "C", Read:0}, 
    {Id: 1, First: "Doe", Last: "D", Read:1}, 
    {Id: 1, First: "Alpha", Last: "B", Read:1}, 
    {Id: 1, First: "Beta", Last: "C", Read:null}, 
    ]; 

var output = [ 
    {Id: 1, First: "Alpha", Last: "B", Read:1}, 
    {Id: 1, First: "Doe", Last: "D", Read:1}, 
    {Id: 1, First: "Beta", Last: "C", Read: null}, 
    {Id: 1, First: "John", Last: "B", Read:0} 
    {Id: 1, First: "Jane", Last: "C", Read:0}, 
]; 
+1

添加输入和预期的输出到你的问题。 –

+0

编辑了一些数据 – Devyiweid

回答

1

好像你只是要排序多个字段。首先排序读状态,然后按姓氏,然后按名字(不区分大小写),你可以:

var data = [ 
 
    {Id: 1, First: "John", Last: "B", Read:0}, 
 
    {Id: 1, First: "Jane", Last: "C", Read:0}, 
 
    {Id: 1, First: "Doe", Last: "D", Read:1}, 
 
    {Id: 1, First: "Alpha", Last: "B", Read:1} 
 
]; 
 

 
data.sort((a, b) => 
 
    b.Read !== a.Read 
 
    ? b.Read - a.Read 
 
    : a.Last.toLowerCase().localeCompare(b.Last.toLowerCase()) 
 
     ? a.Last.toLowerCase().localeCompare(b.Last.toLowerCase()) 
 
     : a.First.toLowerCase().localeCompare(b.First.toLowerCase())); 
 
    
 
console.log(data);

更新

为了应对这样的事实Read字段的null值(反直觉)被认为是truthy,您必须引入一对临时变量(let aRead = a.Read != null a.Read : 1)和比较这些,或改写的比较如下:

var data = [ 
 
    {Id: 1, First: "John", Last: "B", Read:0}, 
 
    {Id: 1, First: "Jane", Last: "C", Read:0}, 
 
    {Id: 1, First: "Doe", Last: "D", Read:1}, 
 
    {Id: 1, First: "Alpha", Last: "B", Read:1}, 
 
    {Id: 1, First: "Beta", Last: "C", Read:null} 
 
]; 
 

 
data.sort((a, b) => 
 
    b.Read !== a.Read 
 
    ? (b.Read != null ? b.Read : 1) - (a.Read != null ? a.Read : 1) 
 
    : a.Last.toLowerCase().localeCompare(b.Last.toLowerCase()) 
 
     ? a.Last.toLowerCase().localeCompare(b.Last.toLowerCase()) 
 
     : a.First.toLowerCase().localeCompare(b.First.toLowerCase())); 
 
    
 
console.log(data);

+0

它的排序,然后根据读取状态(concat)进行分组,查看我的答案以获得想法或任何改进。未读的消息到顶部(按姓氏按字母顺序排列),其余按底部(也按字母顺序排列) – Devyiweid

+0

@Devyiweid无需分组,过滤或连接。你可以对待一切都是一种。我的输出符合您的预期输出。 –

+0

感谢Robby对本质上基本上是一种排序的洞察力,我对'Read:null'记录有点问题,添加到我的输入中,请再次提醒。 – Devyiweid

0

只动mapsort功能集成到自己的命名函数并重新使用它们:

// helpers 
function processItem(item) { 
    return {Id: item.Id, First: item.First.toLowerCase(), Last: item.Last.toLowerCase()} 
} 

function sortItemByLast(a, b) { 
    if (a.Last < b.Last) return -1; 
    if (a.Last > b.Last) return 1; 
    return 0; 
}; 

// process data 
var unread = data.filter(function(item){ 
    return item.Read == 0; 
}).map(processItem).sort(sortItemByLast); 

var read = data.filter(function(item){ 
    return item.Read == null || item.Read == 1; 
}).map(processItem).sort(sortItemByLast); 


var finalData = unread.concat(read); 
0

您可以sort,然后再使用reduce积累结果:

var data = [ 
 
    {Id: 1, First: "John", Last: "B", Read:0}, 
 
    {Id: 1, First: "Jane", Last: "C", Read:0}, 
 
    {Id: 1, First: "Doe", Last: "D", Read:1}, 
 
    {Id: 1, First: "Alpha", Last: "B", Read:1} 
 
]; 
 

 
var result = data.sort(function(a, b){ 
 
    if (a.Last < b.Last) return -1; 
 
    if (a.Last > b.Last) return 1; 
 
    return 0; 
 
}).reduce(function(res, o) { 
 
    var newO = {Id: o.Id, First: o.First.toLowerCase(), Last: o.Last.toLowerCase()}; // the object to be pushed to either the read or unread array (if you are not using the old object o, then just remove the property "Read" from it and use it without creating a new object) 
 
    res[o.Read == 0? "unread": "read"].push(newO); // push o to either the read or unread array, depending on the property "Read" 
 
    return res; 
 
}, {read: [], unread: []});       // the initiale value will be an object containing two arrays (one for read and one for unread objects) 
 

 
console.log(result);

+0

你可以请标签(读/未读)删除,看到我的输出。可能吗?谢谢 – Devyiweid

+0

请也看我的答案任何改进 – Devyiweid

+0

@Devyiweid这并不难。该对象包含这两个数组。看到新的编辑。 –