Loop While node implementation

Hi!

I’m new at dynamo and i’m having a bit of trouble implementing the loop while node. I’ve looked up the forum for everything related to this node but still can’t get this to work.

I’m trying to develop a function that imports text from a Revit General Annotation object, looks up the translation on a custom “dictionary” developed by the user (Excel file), and then writes back the translated text in another field of the Annotation.

I’ve managed to get everything to work except the loop part. The capture I’m posting is from a simplified version of this function where I’m just trying to write a constant value “Z” while going through the list of all the imported Annotative objects. The loop should increment the “index” value each time it runs (highlighted in red at the capture).

any help is appreciated! Thanks

Capture

1 Like

The loop while node is not easy to implement. Here’s one example:

http://dynamobim.com/forums/topic/there-are-a-few-numbers-how-can-you-sort-them-into-3-bowls/#post-19036

So to perform a successful while loop, we need an initial object (init, it can be an integer, an element, a list, etc.), an action to perform on the object for each cycle of the loop (loopBody, it has to be a function object) and a condition to terminate the loop (continueWhile, again has to be a function object).

In the example above I have a list of numbers and each cycle of the loop I remove an item from that list, until the sum of the resulting list equals or is less the sum of the initial list.

In your case, your initial object is a 0. An integer doesn’t have any parameters to set, so the first problem is your loop action. Also note that the SetParameter node isn’t acting as a function.

Your termination condition is failing because it’s also not a function. Note that your code block node with “index” outputs a null value. CBNs can’t act as function objects yet. Also “index” doesn’t refer to anything, it’s just an empty variable and thus it returns a null.

I suggest you try to avoid the loop while node for now and instead break the process into steps, maybe something along the lines of this:

1 Like

Hi Dimitar, thanks for the reply.

I was aware that I had to have some kind of recursion somewhere. I didn’t know about List Map. That’s a much simpler way of using a looped function than Loop While.

The thing is that it seems that some nodes don’t work well within the function. So that would be a serious limitation. Please check capture below:

All functions work with “List.Map”, the thing is that you need to know what the function expects :slight_smile:

“List.GetItemAtIndex” needs an integer value that represents the position of the object in the list (the first element will be 0, the second 1, etc ). You don’t really need to use “List.Map” with it because it can already handle lists of integers.

However, if you have nested lists, mapping the “GetItemAtIndex” function can help you process each nested list on its own. Alternatively you could also use node lacing in such cases.

 

To be honest it’s a little hard for me to follow your intention. Are you trying to merge each pair of strings from the two lists?

OK. Thank you for your reply. Here’s what I’m trying to do:

I’m trying to translate automatically a list of terms. I have a dictionary composed of two lists, the first with the original terms, and the other to the corresponding translation terms.

I’m trying to go through each term to translate from the “to be translated” list (Get Item at Index), find where it is on the “dictionary - original terms” list (Index Of), and use the location to find the translated term on the “dictionary - translated terms” (Get Item at Index). This should produce a new list with all the terms translated, but I can’t get it to work. Index OF doesn’t seem to work with the iterations.

All of this trouble comes because the Index Of node accepts only one element at a time (correct me if I am wrong). So I’m trying to find a way to make it work on a loop, with one term at a time, going through all the list to be translated. That’s why I was trying to use the node Loop While in the first post.

Hi Andre,

Are you looking for this.

In that case , you could try the “Dictionary.ByKeysValues” node from spring nodes.

2015-11-14_14-02-58

Lunchbox has a few nodes that can also be used to create dictionaries - you can try them as well:

http://www.theprovingground.org/2015/04/back-to-basics-with-lunchbox-and-dynamo.html

Hey guys, thanks a lot for your help, really.

KULKUL, your solution is very interesting, the thing is forgot to mention that I need it to work with and undefined number of “dictionary terms” and in your case I see that one would have to create new instances of the ReplaceItemAtIndex node for each new word of the dictionary. Thanks.

DIMITAR, your solution is exactly what I needed, of course. I’m a bit frustrated I couldn’t get this to work wth a standard node based solution, but that works perfectly and it will be extremely helpful at the office work. Thanks.

Anyway this is a helpfull exercise for begginers like me and I will continue to look for some other solutions just as a learning exercise with Dynamo.

One thing that I realized is that if the Index Of node worked for multiple elements, this would have been much easier to implement with standard nodes. Because it only worked for one element at the time, I was trying to make it to work iteratively. either with the LoopWhile node or with the ListMap node. So i’m sliding in this as a suggestions for developers. Unless of course it already exists. but at least I couldn’t find it.

Anyway, here is my working solution.

Capture

Capture2

Well, if you prefer to use the standard nodes, this exact principle is definitely doable with them as well :

I only suggested dictionaries because they might perform better for large data sets.

wow! this is much simpler that I thought, thanks for clarifing how to do this with standard nodes. I’ll definitely spend some more time to understand how nodes work as functions.

I’ll be using your node anyway, but it’s good to understand. Thanks for the tip.