【问题标题】:Filter JSON array leaving all MAX values in JavaScript过滤 JSON 数组,将所有 MAX 值保留在 JavaScript 中
【发布时间】:2017-11-11 16:18:29
【问题描述】:

这里是原始数组,

var dates = 
[ { user_id: '1', week_number: '2', amount: '100' },
  { user_id: '1', week_number: '2', amount: '100' },
  { user_id: '1', week_number: '2', amount: '100' },
  { user_id: '1', week_number: '3', amount: '100' },
  { user_id: '3', week_number: '3', amount: '100' } ]

更新

首先,我尝试按最高 week_number 值对数组进行排序:

var x = dates.sort(function (itemA, itemB) {
  return itemA.week_number < itemB.week_number; 
  }); 

得到:

[ { user_id: '1', week_number: '3', amount: '100' },
  { user_id: '3', week_number: '3', amount: '100' },
  { user_id: '1', week_number: '2', amount: '100' },
  { user_id: '1', week_number: '2', amount: '100' },
  { user_id: '1', week_number: '2', amount: '100' } ]

然后使用.filter得到

[ { user_id: '1', week_number: '3', amount: '100' },
  { user_id: '3', week_number: '3', amount: '100' },]

后来我找到了reduce 方法,但它只返回一个具有最高week_number 值的对象。

var max = dates.reduce(function(prev, current) {
  return (prev.week_number > current.week_number) ? prev : current
    })

正如您将看到的,.filter 将完成工作。

非常感谢您提供的所有答案。你是最棒的!!!

【问题讨论】:

  • 它应该显示包含'4'的对象的数组
  • 我的意思是,如果只有一个 week_number: '4' 和多个 week_number: '3' 怎么办?
  • 应该有包含week_number: 'max'的对象的数组
  • 如果你能保证列表是week_number排序的,那么你需要做的就是在末尾开始一个循环,并在week_number变化时中断。
  • 你不需要对数组进行排序,因为你只需要一个循环来获取想要的对象。

标签: javascript arrays json filter


【解决方案1】:

使用map方法获取所有week_number。从这个数组中获取最大值,现在在filter方法中使用这个最大值来获取匹配对象

var dates = [{
    user_id: '1',
    week_number: '2',
    amount: '100'
  },
  {
    user_id: '1',
    week_number: '2',
    amount: '100'
  },
  {
    user_id: '4',
    week_number: '4',
    amount: '100'
  },
  {
    user_id: '1',
    week_number: '2',
    amount: '100'
  },
  {
    user_id: '1',
    week_number: '3',
    amount: '100'
  },
  {
    user_id: '3',
    week_number: '3',
    amount: '100'
  }
]

var o = dates.map(function(item) {
  return +item.week_number;
}).sort(function(a, b) {
  return a - b
})[dates.length - 1]
console.log(o)
var m = dates.filter(function(elem) {
  return elem.week_number === o.toString();
})
console.log(m)

编辑

上面代码中的map函数是多余的,对日期进行排序会得到week_number最大的对象,然后可以使用过滤器得到想要的结果

var dates = [{
    user_id: '1',
    week_number: '2',
    amount: '100'
  },
  {
    user_id: '1',
    week_number: '2',
    amount: '100'
  },
  {
    user_id: '4',
    week_number: '4',
    amount: '100'
  },
  {
    user_id: '1',
    week_number: '2',
    amount: '100'
  },
  {
    user_id: '1',
    week_number: '3',
    amount: '100'
  },
  {
    user_id: '3',
    week_number: '3',
    amount: '100'
  }
]

var o = dates.sort(function(a, b) {
  return a.week_number - b.week_number
})[dates.length - 1]

var m = dates.filter(function(elem) {
  return elem.week_number === o.week_number;
})
console.log(m)

【讨论】:

  • 如果数组中间有 { user_id: '4', week_number: '4', amount: '100' } 项,这将不起作用
  • 为什么是.map()? OP 的原始.reduce() 会更好(进行一些修复)。如果你可以假设最大的week_number 在最后,那么.map() 完全是多余的,因为你可以只做var o = dates[dates.length-1].week_number
  • 为什么不将数组的最后一个值作为最大值。如果数据按week_number排序,则不需要映射。
  • @NinaScholz 我同意地图根本不需要
  • 为什么复杂的.sort() 比原来的.reduce() 更好? .reduce() 的时间复杂度要低得多。
【解决方案2】:

您可以通过检查week_number 并在必要时替换结果集来使用单循环方法。

var dates = [{ user_id: '1', week_number: '2', amount: '100' }, { user_id: '1', week_number: '2', amount: '100' }, { user_id: '1', week_number: '2', amount: '100' }, { user_id: '1', week_number: '3', amount: '100' }, { user_id: '3', week_number: '3', amount: '100' }],
    result = dates.reduce(function (r, o, i) {
        return !i || r[0].week_number < o.week_number
            ? [o]
            : r[0].week_number === o.week_number
                ? r.concat(o)
                : r;
    }, []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

  • 如果最后一项是{ user_id: '4', week_number: '4', amount: '100' },这将不起作用
  • @RomanPerekhrest,对,我认为应该尊重 id。
  • 无论如何,OP似乎没有考虑任何其他方法
【解决方案3】:

reduce 可能不是完成此任务的最佳工具。相反,循环式的解决方案可能更好:

var maxWeek = 0;
var max = [];
dates.forEach(function(date) {
    const week = date.week_number;
    if (week > maxWeek) {
        maxWeek = week;
        max = [date];
    }
    else if (week === maxWeek) {
        max.push(date);
    }
});

注意:我没有测试过这段代码,所以我不能保证没有错误。

【讨论】:

    【解决方案4】:

    带有Array.sort()功能:

    最初的例子被扩展了额外的项目:

    var dates = [{ user_id: '1', week_number: '2', amount: '100' }, { user_id: '1', week_number: '2', amount: '100' }, { user_id: '1', week_number: '2', amount: '100' }, { user_id: '1', week_number: '3', amount: '100' }, { user_id: '3', week_number: '3', amount: '100' }, { user_id: '4', week_number: '4', amount: '100' }],
        result = [];
    
    dates.sort(function(a, b){ return +b.week_number - +a.week_number; });
    result.push(dates[0]);
    for (var i=2, len = dates.length; i<=len; i++) {
        if (dates[i].week_number != result[0].week_number) break;
        result.push(dates[i]);
    }
    console.log(result);

    【讨论】:

      【解决方案5】:
       var res = [], prev, max;
       for (var i = 0, len = dates.length; i < len; i++) {
         max = parseInt(dates[i].week_number);
         if (!res.length) {
          prev = max; res.push(dates[i]);
         } else if (prev === max) {
          res.push(dates[i]);
         } else if (max > prev) {
          prev = max; res.length = 0; res.push(dates[i]);
        }
      }
      

      【讨论】:

        【解决方案6】:

        鉴于列表按week_number 排序,这只是一个简单的反向循环。

        var dates = [{ user_id: '1', week_number: '2', amount: '100' }, { user_id: '1', week_number: '2', amount: '100' }, { user_id: '1', week_number: '2', amount: '100' }, { user_id: '1', week_number: '3', amount: '100' }, { user_id: '3', week_number: '3', amount: '100' }];
        
        var i = dates.length;
        var last = dates[--i];
        while (--i !== -1 && dates[i].week_number === last.week_number) {
        }
        
        var res = dates.slice(i+1);
        console.log(res);

        或者使用.reduceRight(),虽然你不能停止循环。

        var dates = [{ user_id: '1', week_number: '2', amount: '100' }, { user_id: '1', week_number: '2', amount: '100' }, { user_id: '1', week_number: '2', amount: '100' }, { user_id: '1', week_number: '3', amount: '100' }, { user_id: '3', week_number: '3', amount: '100' }];
        
        var res = dates.reduceRight((a, obj) => 
          a.length && obj.week_number !== a[a.length-1].week_number ? a : [obj, ...a]
        , []);
        
        console.log(res);

        但是,如果您不能依赖列表的排序顺序,那么您应该使用您已经编写的.reduce(),并将其结果用于.filter() 操作。

        var dates = [{ user_id: '1', week_number: '2', amount: '100' }, { user_id: '1', week_number: '2', amount: '100' }, { user_id: '1', week_number: '2', amount: '100' }, { user_id: '1', week_number: '3', amount: '100' }, { user_id: '3', week_number: '3', amount: '100' }];
         
        var max = dates.reduce((p, c) => +p.week_number > +c.week_number ? p : c).week_number;
        var res = dates.filter(d => d.week_number == max)
        
        console.log(res);

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-08-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多