2016-12-01 1 views
1

Кто-то, пожалуйста, помогите мне с моим титулом на этот вопрос.Как отсортировать массив JavaScript более вложенными объектами в массивах и захватить верхнюю ###?

Dummy пример. У меня есть массив объектов:

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. Buick (дешевое дополнение были $ 35, значение, используемое для сравнения)
  2. Jeep (самый дешевый надбавка составляла 50 долларов США, использовалось для сравнения)
+0

ваши дополнения будет иметь имена, или они просто стоят? Потому что, если вы просто храните пару 1 квар, у меня нет смысла хранить объект в массиве – Fallenreaper

+0

Я просто лишил его 99%, чтобы ответить - да :) – user1447679

+0

'plans' - это объект, а не массив. –

ответ

1

Так что я бы сделать, это накормить всех из них в массив, а затем отсортировать его по стоимости. Это был бы мой наивный подход. Более оптимальным решением было бы хранить только 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; 

это более интересный дизайн будет толкать первые 2 в списке, но тогда это будет найти самый большой из 2-х затрат, а затем проверяет, если новый - меньше. Если новый будет меньше item[index], он будет заменен.

Это никогда не будет иметь массив больше, чем 2, так что занимает меньше памяти

0

Мне пришлось поиграть с объект, но вот суть его -

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); 
 
}

В принципе, вам нужно вернуть a-b в функции сортировки, где a и b являются низкими значениями аддона. Таким образом, я вычислил максимальное количество обоих автомобилей при сравнении, и использовал эти значения, чтобы решить, что происходит.

Edit: Я вижу, что вы обновили объект JS, ответ должен быть похож на минимум, вам нужно будет только выяснить, какие plan использовать для a и b. Вы можете сделать так, чтобы мое использование функции Math.max

+0

Я сделал ошибку, чтобы упростить мой код для примера. Планы - это массив. – user1447679

+0

Хорошо, я добавил примечание – casraf

+0

Спасибо. Попытка понять это сейчас. Только один из тех изгибов мозга. – user1447679

0

Один простой способ сделать это - сначала отсортировать аддоны по цене (если вы не возражаете против побочного эффекта, который аддоны останутся отсортированными по цене).

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 example

1

Другой подход. При таком подходе исходные данные не будут отсортированы или изменены.

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));

0

Используя данные @ 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; 
}); 

Line 2 сорта друг Автостекла addons массив от низкого до высокого. Строка 5 сортирует cars от низкого до высокого на основании первого индекса их соответствующего addons.

Если синтаксис ES6 сбивает с толку, here's a translation to ES5

0

Я предлагаю использовать sorting with map, а затем взять верхние 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; }

Смежные вопросы