0 votes
by (680 points)

Hi everyone,

Let's say I have the following code:

<<set $Sara to {Strength: 10, Intelligence: 15, Agility: 10}>>
<<set $Rob to {Strength: 15, Intelligence: 10, Agility: 10}>>
<<set $Dennis to {Strength: 15, Intelligence: 5, Agility: 15}>>
<<set $party_members to {$Sara, $Rob, $Dennis}>>

How do I return the object from the $party_members array with the highest .Strength property?  And like in my example above, both $Rob and $Dennis have an identical .Strength property.  Is it possible to randomly return one of them if the desired property value is tied in first place?

Thanks.

3 Answers

+1 vote
by (44.7k points)
selected by
 
Best answer

As your code is above, $party_members isn't right.  For an array you should use [].  The {} is for objects.  That line should be:

<<set $party_members to [$Sara, $Rob, $Dennis]>>

Once you fix that, the code should be something like this:

<<if $party_members.length > 0>>
	<<set _HiBags = [ 0 ]>>
	<<set _HiVal = $party_members[0].Strength>>
	<<if $party_members.length > 1>>
		<<for _i = 1; i < $party_members.length; _i++>>
			<<set _Value = $party_members[i].Strength>>
			<<if _Value > _HiVal>>
				<<set _HiVal = _Value>>
				<<set _HiBags = [ _i ]>>
			<<elseif _Value === _HiVal>>
				<<set _HiBags.push( _i )>>
			<</if>>
		<</for>>
	<</if>>
	<<set _member_index = _HiBags[ random(_HiBags.length - 1) ]>>
<</if>>

After that you can use "$party_members[_member_index]" to get the result.

Basically, that creates an array of entries that are tied with the highest value seen so far, resetting the array whenever it finds a new highest value. At the end you just randomly pick one from that array of the items with the highest values.

(NOTE: I modified the above from some JavaScript I have that does the same thing, so there might be bugs, but it should be close.)

by (8.6k points)

Or a bit shorter:

<<set _HiVal = $party.map(o => o.Strength).reduce((a, b) => Math.max(a, b))>>
<<set _member = $party.filter(o => o.Strength === _HiVal).random()>>

And if you want the property to be an argument itself (in _property):

<<set _HiVal = $party.map(o => o[_property]).reduce((a, b) => Math.max(a, b))>>
<<set _member = $party.filter(o => o[_property] === _HiVal).random()>>

 

by (44.7k points)

Neat trick, Akjosch.  Thanks. smiley

0 votes
by (63.1k points)

Math.max() returns the highest value in a list of numbers.  To get that to work with an array, you can use the spread operator (...).

<<set $array to [0, 10, 15, 4, -6, 8]>>
<<set $highest to Math.max(...$array)>>

$highest /% should be 15 %/

The spread operator doesn't work in Internet Explorer.  If you want to do it without using the spread operator, you can use one of these instead:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/max#Getting_the_maximum_element_of_an_array

 

by (44.7k points)
That won't work because $party_members is an array of objects, not an array of numbers.
0 votes
by (23.6k points)

I think the answer given here may contain what you are looking for.

...