JavaScript对象数组按属性最小值筛选

7

我需要按'rest'属性的最小值筛选此对象数组。这是一种方法。还有其他方法吗?

'data'变量是链接函数的结果。是否有其他方法可以在Math.min()函数内部不再调用'data'变量。

let data = 
[ { size: 5, qty: 2, rest: 0 },
  { size: 2, qty: 5, rest: 0 },
  { size: 1, qty: 10, rest: 0 },
  { size: 3, qty: 3, rest: 1 },
  { size: 4, qty: 2, rest: 2 } ]

let result = data.filter(e=> e.rest === Math.min(...data.map(f=>f.rest) ) );
console.log(result);

// result is
//[ { size: 5, qty: 2, rest: 0 },
//  { size: 2, qty: 5, rest: 0 },
//  { size: 1, qty: 10, rest: 0 }]

5个回答

11
最简单的方法是将min函数从过滤器中提取出来,如下所示:
let min = Math.min(...data.map(item => item.rest))

这样做更高效,因为我们不再循环遍历数据以找到每次筛选的最小值。

现在我们有了n * 2次遍历而不是n^2次遍历。 (n是您的数据集的大小,在此例中为5)

以下是完整示例:

let data = [ 
  { size: 5, qty: 2, rest: 0 },
  { size: 2, qty: 5, rest: 0 },
  { size: 1, qty: 10, rest: 0 },
  { size: 3, qty: 3, rest: 1 },
  { size: 4, qty: 2, rest: 2 } 
]

let min = Math.min(...data.map(item => item.rest))
let result = data.filter(item => item.rest === min)
console.log(result)

希望这能帮到您! Lloyd

谢谢。是的,我错过了那个问题。难道没有其他方法可以使用方法链来完成这个任务吗? - Crizy Sash
你总是需要将剩余的值与最小变量或预定义的阈值进行比较,你的初始帖子是方法链的一个例子。 - Lloyd
无论如何还是谢谢。 :) - Crizy Sash

4

data.filter 中的 data.map 的时间复杂度为 O(N^2);要想达到 O(N) 的解决方案,需要预先迭代 data 来计算最小值,然后按照该最小值进行 filter

let data = 
[ { size: 5, qty: 2, rest: 0 },
  { size: 2, qty: 5, rest: 0 },
  { size: 1, qty: 10, rest: 0 },
  { size: 3, qty: 3, rest: 1 },
  { size: 4, qty: 2, rest: 2 } ];
const minRest = Math.min(...data.map(({ rest }) => rest));

let result = data.filter(({ rest }) => rest === minRest);
console.log(result);


谢谢。我错过了那个。但这不是我要找的。有没有其他方法可以不声明变量? - Crizy Sash
很遗憾,如果您想要 O(N) 的性能,您必须声明或使用另一个变量。(如果您不想将其暴露给外部作用域,可以将其放入 IIFE 中) - CertainPerformance

2

我认为最简单/最好的解决方案是@CertainPerformance给你的那个。

只想再添加一个具有线性运行时间的解决方案(仅对数组进行一次迭代)

let data = [
  { size: 5, qty: 2, rest: 0 },
  { size: 2, qty: 5, rest: 0 },
  { size: 1, qty: 10, rest: 0 },
  { size: 3, qty: 3, rest: 1 },
  { size: 4, qty: 2, rest: 2 } 
];

let result = data.reduce((result, item) => {
  let minRest = result.length? result[0].rest: item.rest;

  if (item.rest < minRest) {
    minRest = item.rest;
    result.length = 0;
  }

  if (item.rest === minRest) {
    result.push(item);
  }

  return result;
}, []);

console.log(result);

@mathieux51给了我另一个想法,可以在方法链中完成此操作,但可读性/清晰度/意图不如其他方法:

let data = [
  { size: 5, qty: 2, rest: 0 },
  { size: 2, qty: 5, rest: 0 },
  { size: 1, qty: 10, rest: 0 },
  { size: 3, qty: 3, rest: 1 },
  { size: 4, qty: 2, rest: 2 } 
];

let result = data.sort((a, b) => a.rest - b.rest)
                 .filter((item, index, array) => item.rest === array[0].rest);

console.log(result);


非常感谢。最后一个是我要找的。 - Crizy Sash
1
排序的时间复杂度为O(N log N) - CertainPerformance

0

获取最小值或最大值 由于没有人提到这种方法,我在这里进行更新。

myArray.sort(function (a, b) {
return a.rest - b.rest
})

var min = myArray[0],
max = myArray[myArray.length - 1]

它具有良好的可读性/清晰度/意图。


0

听起来你想要对列表进行排序。我会按照以下方式实现:

const result = data.sort((a, b) => a.rest - b.rest)

按最小的“rest”值排序和过滤。 - Crizy Sash
只进行排序也可以。获取第一个或最后一个项目,即为最小值和最大值。 - Mustkeem K

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接