繁体   English   中英

如何通过数组中更多嵌套对象对JavaScript数组进行排序,并抢占顶部###?

[英]How to sort a JavaScript array by more nested objects in arrays and grab the top ###?

这是一个虚拟的例子。 我有一个对象数组:

var cars = [
  { 
    name: "Hyundai",
    plans: [
      {
        name: "Something",
        add-ons: [
            {
               cost: 100
            },
            {
               cost: 75
            }
        ] 
      }, { ... }
    ]
  },
  { 
    name: "Jeep",
    plans: [
      {
        name: "Something",
        add-ons: [
            {
               cost: 50
            },
            {
               cost: 75
            }
        ] 
      }, { ... }
    ]
  },
  { 
    name: "Buick",
    plans: [
      {
        name: "Something",
        add-ons: [
            {
               cost: 35
            },
            {
               cost: 50
            }
        ] 
      }, {...}
    ]
  }
]

我想做的是找到最便宜的前2名汽车,并通过另一个变量引用它们。

像这样:

var top2 = findTopTwo(cars);

findTopTwo(arr) {
  return arr.sort(function(a, b) {
    // My trouble spot
  }).slice(0, 2);
}

在我的简单示例中,top2的结果为:

  1. 别克(最便宜的附加组件是$ 35,用于与进行比较的值)
  2. 吉普车(最便宜的附加组件是$ 50,用于与进行比较的价值)

因此,我要做的就是将它们全部馈入一个数组,然后根据成本对其进行排序。 那将是我的幼稚方法。 最佳的解决方案是在给定时间仅存储2个对象,而不是所有项目的列表。

天真的方法很简单:

var items = [];
for ( var i in cars ){
  var car = cars[i];
  for (var i in car["plans"]){
    for (var j = 0; j < car["plans"][i]["add-ons"]){
      items.push({"name": car.name, "cost": car["plans"][i]["add-ons"][j]["cost"]});
    }
  }
}
return items.sort(function(a,b){ return a.cost < b.cost }).slice(0,2);

那将返回2个对象的列表,该对象包含汽车的名称和成本。 更有效的方法是执行以下操作:

var biggest = function(arr){
  if (arr.length < 2 ) return -1;
  return arr[0].cost > arr[1].cost ? 0 : 1;
}
var items = [];
for ( var i in cars ){
  var car = cars[i];
  for (var i in car["plans"]){
    for (var j = 0; j < car["plans"][i]["add-ons"]){
      var obj = {"name": car.name, "cost": car["plans"][i]["add-ons"][j]["cost"]};
    }

    var index = biggest(items)
    if (index < 0){
      items.push(obj);
    }else{
      if (items[index].cost > obj.cost)
        items[index] = obj;
    }

  }
}
return items;

这种更有趣的设计会将前两个成本推入列表,但随后它将找到这两个成本中的最大成本,然后检查新成本是否小于它。 如果新的小于item[index] ,它将被替换。

该数组永远不会大于2,因此占用的内存更少

另一种方法。 通过这种方法,您的原始数据将不会被排序或修改。

 var cars=[{name:"Hyundai",plans:[{name:"Something","add-ons":[{cost:100},{cost:75}]}]}, {name:"Jeep",plans:[{name:"Something","add-ons":[{cost:50},{cost:75}]}]}, {name:"Buick",plans:[{name:"Something","add-ons":[{cost:35},{cost:50}]}]}]; function findTopTwo(cars) { return cars.map( car => car.plans.reduce( (prevPlan, plan) => plan['add-ons'].reduce((prevAddOn, addOn) => { if (prevAddOn.cost > addOn.cost) { prevAddOn.cost = addOn.cost; } return prevAddOn; }, prevPlan), { cost: Number.MAX_VALUE, name: car.name }) ) .sort((a, b) => a.cost - b.cost) .slice(0, 2) .map(item => item.name); } console.log(findTopTwo(cars)); 

我不得不试玩这个对象,但这是要点-

 var cars = [{ name: "Hyundai", plans: { addons: [{ cost: 100 }, { cost: 75 }] } }, { name: "Jeep", plans: { addons: [{ cost: 50 }, { cost: 75 }] } }, { name: "Buick", plans: { addons: [{ cost: 35 }, { cost: 50 }] } }]; var top2 = findTopTwo(cars); console.log(top2); function findTopTwo(arr) { return arr.sort(function (a, b) { // this map outputs array of costs: [35, 40] // and Math.min takes the lowest value of each var a_max_cost = Math.min.apply(null, a.plans.addons.map(function(i){i.cost})), b_max_cost = Math.min.apply(null, b.plans.addons.map(function(i){i.cost})); return a_max_cost - b_max_cost; }) .slice(0, 2); } 

基本上,您需要在sort函数中返回ab ,其中ab是最低附加值。 因此,我在比较时计算了两辆车的最大值,并使用这些值来决定哪辆车去哪儿。

编辑:我看到您已经更新了JS对象,答案应该类似于min,您只需要弄清楚对ab使用哪个plan 您可以执行类似于我对Math.max函数的使用

一种简单的实现方法是先按价格对插件进行排序(如果您不介意插件的副作用,然后按价格进行排序)。

function findTopTwo(arr) {
  arr.forEach(function (elem) {
    elem.plans.addons = elem.plans.addons.sort(function (a, b) {
      return a.cost > b.cost;
    });
  });
  return arr.sort(function(a, b) {
    return a.plans.addons[0].cost > b.plans.addons[0].cost;
  }).slice(0, 2);
}

jsbin示例

使用@casraf的数据:

const sortedCars = cars.map(car => {
    car.plans.addons.sort((a, b) =>  a.cost - b.cost);
    return car;
}).sort((a, b) => {
    return a.plans.addons[0].cost - b.plans.addons[0].cost;
});

第2行按从低到高的顺序对每辆汽车的addons排序。 第5行根据其相应的addons属性的第一个索引将cars从低到高排序。

如果ES6语法令人困惑, 这是对ES5的翻译

我建议对地图进行排序 ,然后选择前2个条目并从cars获取数据。

 var cars = [{ name: "Hyundai", plans: [{ 'add-ons': [{ cost: 100 }, { cost: 75 }] }] }, { name: "Jeep", plans: [{ 'add-ons': [{ cost: 50 }, { cost: 75 }] }] }, { name: "Buick", plans: [{ 'add-ons': [{ cost: 35 }, { cost: 50 }] }] }], cost = cars. map(function (a, i) { return { index: i, cost: a.plans.reduce(function (r, b) { return Math.min(r, b['add-ons'].reduce(function (s, c) { return Math.min(s, c.cost); }, Infinity)); }, Infinity) }; }). sort(function (a, b) { return a.cost - b.cost; }), top2 = cost.slice(0, 2).map(function (a) { return cars[a.index]; }); console.log(top2); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM