0

I am trying to generate a mapping of triangles to determine how they are connected to one another. To do this, I need to store the indices of any triangle into an array (array is clearer to me than a list). The problem is that the array of triangles has two dimensions; the first is the cell number, the second is the pointer to the index, of which there are three. So, a typical declaration for one cell would be:

array set tris {
    1,1 23
    1,2 25
    1,3 34
}

Performing a puts $tris(1,1) results in 23 being printed. However, I want to abstract the cell number using a looping construct like foreach such as:

foreach cell {1 2 3 4 5} {
    set indices [$dom getCell $cell]
    array set tris {
        $cell,1 [lindex indices 0]
        $cell,2 [lindex indices 1]
        $cell,3 [lindex indices 2]
    }
}

In this loop, the [$dom getCell $cell] is a Pointwise command that returns a list of indices that define a triangle, and in this case the $cellth triangle. When I do this, and check the contents of $cells(2,1), I get an error stating, can't read "cells(2,1)": no such element in array. According to the returned value of [$dom getCell $cell], I get 23 25 34 for the first cell to check; so that is correct. But checking the array contents suggests I am not doing something correctly. What am I missing or doing incorrectly?

1
  • In the question, you mention "a typical declaration for one cell." It is helpful in Tcl to remember that there are no declarations like you might find in other languages. Everything is a command and commands take arguments. It's just one of the mindsets you have to drive home to yourself as you improve your abilities in Tcl. Commented Jul 12, 2018 at 19:09

2 Answers 2

2

You could write this

foreach cell {1 2 3 4 5} {
    set indices [$dom getCell $cell]
    set tris($cell,1) [lindex $indices 0]
    set tris($cell,2) [lindex $indices 1]
    set tris($cell,3) [lindex $indices 2]
}

or

foreach cell {1 2 3 4 5} {
    lassign [$dom getCell $cell] tris($cell,1) tris($cell,2) tris($cell,3)
}

or

foreach cell {1 2 3 4 5} {
    set j 0
    foreach elem [$dom getCell $cell] {
        set tris($cell,[incr j]) $elem
    }
}
Sign up to request clarification or add additional context in comments.

Comments

0

Anything enclosed in braces is a literal, so $cell is not getting expanded. You can use parray tris to see exactly what is in there.

Instead, you can use:

foreach cell {1 2 3 4 5} {
    set indices [$dom getCell $cell]
    array set tris [list \
        $cell,1 [lindex $indices 0] \
        $cell,2 [lindex $indices 1] \
        $cell,3 [lindex $indices 2] \ 
        ]
}

(Note the lindex syntax requires the value of the list variable, not the name)

The array set could also be replaced with a for loop with the body setting the array element:

for {set idx 1} {$idx <= 3} {incr idx} {
  set tris($cell,$idx) [lindex $indices [expr {$idx-1}]]
}

2 Comments

Is there a reason that yours and Glenn's examples suggest the array assignment actually be lists? With the array set command, I thought the contents inside {} where nothing more than key,value combinations.
The arguments to the array set command are the name of the array and a list with an even number of elements. That list may be constructed as literals, as you did in the first part of your question. Or the list may be constructed using the list command. Keep in mind that literal lists in Tcl are simply specially formatted strings used in a context where a list is expected by a command.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.