【问题标题】:filter, map, sort and concat过滤、映射、排序和连接
【发布时间】:2017-09-23 04:18:05
【问题描述】:

我觉得可能有更好的解决方案,因为我在以下例程(映射和排序)中重复了代码。

它是具有已读(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},
];

【问题讨论】:

  • 为您的问题添加输入和预期输出。
  • 编辑了一些数据

标签: javascript sorting filter concat


【解决方案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 值被(违反直觉地)认为是真实这一事实,您必须引入几个临时变量(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);

【讨论】:

  • 它正在排序,然后根据读取状态(concat)进行分组,请参阅我的答案以获得想法或任何改进。未读消息放在顶部(按姓氏字母顺序),其余消息放在底部(也按字母顺序)
  • @Devyiweid 不需要分组、过滤或连接。你可以把一切都当作一种。我的输出符合您的预期输出。
  • 感谢 Robby 提供的见解,即本质上它基本上是一种排序,我对 Read:null 记录有一点问题,已添加到我的输入中,请再次提出建议。
  • @Devyiweid 更新了我的答案。
【解决方案2】:

你可以先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);

【讨论】:

  • 能否请您删除标签(已读/未读),请参阅我的输出。可能吗?谢谢
  • 如果有任何改进,请查看我的回答
  • @Devyiweid 这并不难。该对象包含两个数组。查看新的编辑。
  • @KikoGarcia 为什么?
  • @Devyiweid 对不起!我误解了。 Read 属性已删除。阅读 cmets 以获得更多改进,因为我认为没有必要创建新对象。
【解决方案3】:

只需将您的 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);

【讨论】:

    猜你喜欢
    • 2021-04-20
    • 1970-01-01
    • 1970-01-01
    • 2021-06-13
    • 2020-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多