+1 vote
by (1.1k points)
edited by

(twine2.1.3 harlowe 2.0.1)

The harlowe documentation states "The subset can be based on each string's characters, each datamap's values." But how can datamaps be used with find: while still retaining context?

in an other question a datamap with a collection "boxes" with different values is created.

(set: $boxes to (datamap: "green" , 0 , "blue" , 0 , "red" , 0 , "purple" , 0 , "yellow" , 0 , "neon paisley" , 0))
(set: $marbles to 12)
(for: each _drop , ...(range: 1 , $marbles))[
	(set: $boxes's (either: ...(datanames: $boxes)) to it + 1)
	]

I've been using (for:) loops to check the values of each item to see if they match a condition, but this seems expensive, large datamaps cause a noticeable lag for the browser to display the passage. The for loops can also be quite complicated. This seems to be exactly what (find:) is for.

But I'm having trouble using (find:) to check the values in a way which identifies the boxes. I think it may be an issue of combining the proper syntax into the find:.

This

(find: _some where _some is > 0, ...(datavalues: $boxes))

Gives a list of contents > 0 but doesn't identify the box. Makes sense since it's an array of numbers being evaluated. It's also useless, an array of numbers with no context.

Likewise,

(find: _check where _check is not "frog" , ...(datanames: $boxes))

gives a list of the names

But I've found no way to combine the two together which provides names and numbers (effectively making a temporary datamap for display).

(for: each _name , ...(datanames: $boxes))[
	(if: (_name of $boxes) is > 0)[
		_name has (print: (_name of $boxes))]
]

or

{(set: $secondDatamap to (datamap:))
(for: each _name , ...(Datanames: $boxes))[
	(if: (_name of $boxes) is > 0)[
	(set: $secondDatamap to it + (datamap: _name , (_name of $boxes)))
	]
]}
$secondDatamap

seem to be the best method(s).

Am I completely misunderstanding the purpose of find: (this is quite likely!)?

Is there a better way to evaluate and return the values of a datamap while keeping it in context of the value's name? (while using harlowe macros, avoiding java)

1 Answer

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

notes:

1. When using a mathematical comparison operator like > (greater-than) it is best not to also include an is keyword operator, especially when using mathematical operators like >= (greater-than-or-equal-to). Harlowe 2.x was changed to support using is before mathematical operator to better support syntax errors some Author's were making.

Correct: (if: $var > 0 or $var <= 20)[...some code...]

Now supported: (if: $var is > 0 or $var is <= 20)[...some code...]

1. The programming language used by web-browsers is Javascript, not Java, which is a totally unrelated language with an unfortunately similar name.

 

The documentation for the (find:) macro clearly states it searches through values, so it is not the macro you want and unfortunately the only other one you can use is the (for:) macro.

As far as I remember there is also no standard Javascript function to do what you want either, the closest would be the <Array>.map() function but that is for an Array and not a Map object (which is what (datamap:) is using) so you would need to do a for-loop in Javascript similar to what you're doing with TwineScript anyway.

...