2016-10-12 5 views
2

На прошлой неделе у меня были проблемы с простой программой, которую я делаю, и кто-то здесь помог мне. Теперь я столкнулся с другой проблемой. настоящее время у меня этот код:Найти элемент в массиве с использованием взвешенной вероятности и значения

var findItem = function(desiredItem) { 
 
    var items = [ 
 
     { item: "rusty nail", probability: 0.25 }, 
 
     { item: "stone", probability: 0.23 }, 
 
     { item: "banana", probability: 0.20 }, 
 
     { item: "leaf", probability: 0.17 }, 
 
     { item: "mushroom", probability: 0.10 }, 
 
     { item: "diamond", probability: 0.05 } 
 
    ]; 
 
    var possible = items.some(({item, probability}) => 
 
      item === desiredItem && probability > 0); 
 
    if (!possible) { 
 
     console.log('There is no chance you\'ll ever find a ' + desiredItem); 
 
     return; 
 
    } 
 
    var sum = items.reduce((sum, {item, probability}) => sum+probability, 0); 
 
    while (true) { 
 
     var value = Math.random() * sum; 
 
     var lootedItem = items.find( 
 
       ({item, probability}) => (value -= probability) <= 0).item; 
 
     if (lootedItem === 'diamond') break; 
 
     console.log("Dang! A " + lootedItem + " was found..."); 
 
    } 
 
    console.log("Lucky! A " + desiredItem + " was found!"); 
 
} 
 

 
findItem('diamond');

Теперь я хотел бы расширить, добавив еще одно значение, называемое category к items массива. Я хочу, чтобы категории имели значение 2, 5 или 10. Итак, допустим, что элемент diamond будет принадлежать category: 10, а когда выполняется findItem, могут быть найдены только элементы, принадлежащие к той же категории. Я пробовал уже пару дней, но, похоже, не могу об этом подумать. Может, кто-то может помочь подтолкнуть меня в правильном направлении? Заранее спасибо

+0

Используйте ['filter'] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter), чтобы ограничить поиск данной категорией? –

+0

Вы имеете в виду, что * может быть найдено *, что сообщение «Dang!» Может произойти только для этой категории, и все остальные элементы должны быть полностью проигнорированы? – trincot

+0

Спасибо, я посмотрю! –

ответ

3

Вы можете использовать это обновление для этого кода:

// Pass the item list and the desired category as arguments: 
 
var findItem = function(items, category, desiredItem) { 
 
    // apply filter to items, so only those of the given category remain: 
 
    items = items.filter(item => item.category == category); 
 
    // rest of code remains the same: 
 
    var possible = items.some(({item, probability}) => 
 
      item === desiredItem && probability > 0); 
 
    if (!possible) { 
 
     console.log('There is no chance you\'ll ever find a ' + desiredItem); 
 
     return; 
 
    } 
 
    var sum = items.reduce((sum, {item, probability}) => sum+probability, 0); 
 
    var t = 10; 
 
    while (true) { 
 
     var value = Math.random() * sum; 
 
     var lootedItem = items.find( 
 
       ({item, probability}) => (value -= probability) <= 0).item; 
 
     if (lootedItem === desiredItem) break; // fixed this condition! 
 
     console.log("Dang! A " + lootedItem + " was found..."); 
 
     t--; if (t <= 0) throw "loop"; 
 
    } 
 
    console.log("Lucky! A " + desiredItem + " was found!"); 
 
} 
 

 
// Define items here with their category 
 
var items = [ 
 
    { item: "rusty nail", probability: 0.25, category: 2 }, 
 
    { item: "stone",  probability: 0.23, category: 2 }, 
 
    { item: "banana",  probability: 0.20, category: 2 }, 
 
    { item: "leaf",  probability: 0.17, category: 5 }, 
 
    { item: "mushroom", probability: 0.10, category: 5 }, 
 
    { item: "diamond", probability: 0.05, category: 10 } 
 
]; 
 

 
// Call function with extra arguments: 
 
findItem(items, 5, 'mushroom'); 
 

 
console.log('second run:'); 
 
// This will obviously give a hit immediately, as there is only one possible item: 
 
findItem(items, 10, 'diamond');

Изменение:

  • передать больше аргументов в вашу функцию: список предметов и желаемая категория
  • Применить фильтр к списку предметов как первое действие в fu nction
  • Устранить проблему в отношении теста lootedItem - у него был «алмаз» с жестким кодированием.
  • Определите список элементов за пределами функции и добавьте значения категорий для каждого элемента.
  • Адаптировать вызов функции для передачи дополнительных аргументов.
+0

Огромное спасибо вам и благодарю вас за объяснение того, что каждый бит сделал. Я чувствую, что знаю немного больше о кодировании! –

1

Вы хотите что-то вроде этого?

var items = [ { item: "rusty nail", probability: 0.25, category: 10 } 
 
      , { item: "stone",  probability: 0.23, category: 5 } 
 
      , { item: "banana",  probability: 0.20, category: 2 } 
 
      , { item: "leaf",  probability: 0.17, category: 5 } 
 
      , { item: "mushroom", probability: 0.10, category: 2 } 
 
      , { item: "diamond", probability: 0.05, category: 10 } 
 
      ]; 
 

 
findItem("diamond", items); 
 

 
function findItem(needle, haystack) { 
 
    var item = haystack.find(thing => thing.item === needle && 
 
             thing.probability > 0); 
 

 
    if (item) { 
 
     var category = item.category; 
 
     var items = haystack.filter(thing => thing.category === category); 
 
     var sum = items.reduce((sum, thing) => sum + thing.probability, 0); 
 

 
     var value = sum * Math.random(); 
 
     var loot = items.find(thing => (value -= thing.probability) <= 0).item; 
 

 
     while (loot !== needle) { 
 
      value = sum * Math.random(); 
 
      console.log("Dang! A " + loot + " was found..."); 
 
      loot = items.find(thing => (value -= thing.probability) <= 0).item; 
 
     } 
 

 
     return console.log("Lucky! A " + needle + " was found!"); 
 
    } 
 

 
    console.log("There's no chance that you'll ever find a " + needle); 
 
}

Единственное существенное отличие от кода является то, что я использовал filter ограничить поиск.

+0

Спасибо, что указали это! :) –