Iterating over two equal length GH_Structure<GH_Curve>

What would be the simplest method to iterate over two equal length GH_Structure<GH_Curve> collections

For now I am iterating through ech collections like this, but I would like to know how to iterate through both of them within one and the same loop:

            foreach (GH_Curve ghc in c0.AllData(true)) {
                ghc.Value.TryGetPolyline(out Polyline p);
                polys0.Add(p);
            }

            foreach (GH_Curve ghc in c1.AllData(true)) {
                ghc.Value.TryGetPolyline(out Polyline p);
                polys1.Add(p);
            }

I might be misremembering, but doesn’t C# (maybe LINQ) have a zip function? I use this a lot for iterating over N same-length iterables in one terse for loop in Python.

Thanks Anders,

Yes it is possible to have something like this:

            var twoTrees = c0.AllData(true).Zip(c1.AllData(true), (firstGoo,secondGoo) =>  new  { firstGoo, secondGoo }     );

            foreach (var goos in twoTrees) {
                var goo = goos.firstGoo.Value; // Value cannot be accessed anymore as var goo is IGH_Goo here
            }

But after zipping the GH_Curve is made as IGH_Goo, and I cannot access value anymore goos.firstGoo.Value

I was wondering if it is possible to use Enumerator:

            var c0Enumerator = c0.GetEnumerator();
            var c1Enumerator = c1.GetEnumerator();

            while (c0Enumerator.MoveNext() && c1Enumerator.MoveNext()) {
                Object curve0 = c0Enumerator.Current;
                Object curve1 = c1Enumerator.Current;
            }

But this time it casted to object not GH_Curve

Probably I am missing something simple…

Ah, in that case, maybe a normal indexed loop would probably actually be terser and more readable. For reference, in Python zip would be used like this:

for a, b, c in zip(listA, listB, listC):
    # do stuff with a, b, and c

That’s odd, I wouldn’t expect the Zip operator to cast GH_Curve to IGH_Goo - what if you explicitly provide a type identifier?

var twoTrees = c0.AllData(true).Zip(c1.AllData(true), (GH_Curve firstGoo, GH_Curve secondGoo) =>  new  { firstGoo, secondGoo } );

In the second case you’re casting to Object - doesn’t this work?

    ...
    GH_Curve curve0 = c0Enumerator.Current as GH_Curve;
    ...

Wait no, I think I got that the wrong way round - it should be

var twoTrees = c0.AllData(true).Zip(c1.AllData(true), (firstGoo, secondGoo) =>  new  { firstGoo = (firstGoo as GH_Curve) , secondGoo = (secondGoo as GH_Curve) } );

(yeah, Python’s duck-typing is way easier to deal with)

Sorry to be jumping back to this 2 years later, but does this solution work for datatrees?
I’m trying to loop through 2 datatrees simultaneously:
for a, b in zip(treeA, treeB):
but getting this error:
Runtime error (ArgumentTypeException): __getitem__() takes exactly 2 arguments (1 given)
Do you know what’s the problem?

It’s probably simplest to make them Python lists and then iterate over those. You can use the treehelpers explained here:

1 Like