Penn- - 1 month ago 6
Javascript Question

# Find item in array using weighed probability and a value

Last week I had some problems with a simple program I am doing and somebody here helped me. Now I have run into another problem.
I currently have this code:

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

Now I would like to expand on this by adding another value called
`category`
to the
`items`
array. I want the categories to have a value of either
`2`
,
`5`
or
`10`
. So let's say the
`diamond`
item would belong to
`category: 10`
, and when
`findItem`
is executed only items that belong to the same category can be found. I have been trying for a couple of days now but can't seem to get my head around it. Maybe someone can help push me in the right direction? Thanks in advance

You could use this update to that code:

``````// 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');``````

The changes are:

• Pass more arguments to your function: the items list and the desired category
• Apply a filter on the items list as first action in the function
• Fix an issue concerning the `lootedItem` test -- it had "diamond" hard-coded.
• Define the items list outside of the function and add category values to each element.
• Adapt the call of the function to pass the extra arguments.