2017-04-25 36 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這並不難。該對象包含這兩個數組。看到新的編輯。 –