472,977 Members | 1,847 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,977 software developers and data experts.

foreach with parallel iterations of multiple properties

Is it possible to write a foreach so that it simultaneously iterates through
two collections ( or two properties of the same collection ) ?

Following is *only meant as an example* :

-- iterate a dictionary obtaining the next key and value on each iteration.

The following doesn't work

foreach ( string key in MyDictionary.Keys , object value in
MyDictionary.Values )
{
.... but perhaps there's some other way ...


Jul 8 '08 #1
6 5095
John A Grandy wrote:
Is it possible to write a foreach so that it simultaneously iterates through
two collections ( or two properties of the same collection ) ?
No, because there's no meaningful definition of "simultaneous" (what should
happen if one of the iterations is done before the other one?)
Following is *only meant as an example* :

-- iterate a dictionary obtaining the next key and value on each iteration.

The following doesn't work

foreach ( string key in MyDictionary.Keys , object value in
MyDictionary.Values )
{
... but perhaps there's some other way ...
What type is "MyDictionary"? It should implement
IEnumerable<KeyValuePair<TKey, TValue>>, like IDictionary<TKey, TValue>
does. Then it's a matter of writing

foreach (KeyValuePair<string, objectp in MyDictionary) {
string key = p.Key;
object value = p.Value;
...
}

If it's one of the legacy collection types that has no intuitive IEnumerable
implementation, it's a simple matter of iterating over the keys only:

foreach (string key in MyDictionary.Keys) {
object value = MyDictionary[key];
...
}

Of course, since you specify that this is only "an example", you may not be
talking about dictionaries at all. It's always possible to use enumerators
directly for advanced scenarios:

using (IEnumerator<stringiKeys = MyDictionary.Keys.GetEnumerator()) {
using (IEnumerator<objectiObject = MyDictionary.Values.GetEnumerator()) {
// use .MoveNext() and .Current here as you please
}
}

But this is seldom necessary, and the resulting code isn't very readable.

--
J.
Jul 8 '08 #2
Re making it readable... perhaps an extension method (or take of the "this"
in C# 2 to get a static helper method) to walk the two in parallel;
something like below; this could be used i.e.

collectionA.ForEach(collectionB, (a,b)=Console.WriteLine("{0}/ {1}", a,b);

which isn't exactly unreadable...

Marc

public static void ForEach<TLhs, TRhs>(this IEnumerable<TLhs>
leftSequence,
IEnumerable<TRhsrightSequence, Action<TLhs, TRhsaction)
{
if (leftSequence == null) throw new
ArgumentNullException("leftSequence");
if (rightSequence == null) throw new
ArgumentNullException("rightSequence");
if (leftSequence == null) throw new ArgumentNullException("action");
using (var lhs = leftSequence.GetEnumerator())
using (var rhs = rightSequence.GetEnumerator())
{
while (lhs.MoveNext() && rhs.MoveNext())
{
action(lhs.Current, rhs.Current);
}
}
}
Jul 9 '08 #3
On Jul 8, 9:48*pm, Jeroen Mostert <jmost...@xs4all.nlwrote:
If it's one of the legacy collection types that has no intuitive IEnumerable
implementation, it's a simple matter of iterating over the keys only:

* *foreach (string key in MyDictionary.Keys) {
* * *object value = MyDictionary[key];
* * *...
* *}

Of course, since you specify that this is only "an example", you may not be
talking about dictionaries at all. It's always possible to use enumerators
directly for advanced scenarios:

* *using (IEnumerator<stringiKeys = MyDictionary.Keys.GetEnumerator()) {
* * *using (IEnumerator<objectiObject = MyDictionary.Values.GetEnumerator()) {
* * * *// use .MoveNext() and .Current here as you please
* * *}
* *}

But this is seldom necessary, and the resulting code isn't very readable.
This is debateful; personally, I would very much prefer the second
approach you propose to the first, if only because the first does an
unnecessary key lookup for every key, which can be pretty costly in a
loop. If using a legacy collection (I assume you mean Hashtable), then
the proper approach is to obtain an IDictionaryEnumerator from it
explicitly, and use that.
Jul 9 '08 #4
Pavel Minaev wrote:
On Jul 8, 9:48 pm, Jeroen Mostert <jmost...@xs4all.nlwrote:
>If it's one of the legacy collection types that has no intuitive IEnumerable
implementation, it's a simple matter of iterating over the keys only:

foreach (string key in MyDictionary.Keys) {
object value = MyDictionary[key];
...
}

Of course, since you specify that this is only "an example", you may not be
talking about dictionaries at all. It's always possible to use enumerators
directly for advanced scenarios:

using (IEnumerator<stringiKeys = MyDictionary.Keys.GetEnumerator()) {
using (IEnumerator<objectiObject = MyDictionary.Values.GetEnumerator()) {
// use .MoveNext() and .Current here as you please
}
}

But this is seldom necessary, and the resulting code isn't very readable.

This is debateful; personally, I would very much prefer the second
approach you propose to the first, if only because the first does an
unnecessary key lookup for every key, which can be pretty costly in a
loop.
Meh. If it's a dictionary type, the lookup time shouldn't matter except in
pathological cases. Getting an explicit enumerator for the values isn't
necessarily faster (I'll grant you that it probably isn't any *slower*,
though, since the implementation could always use the key-lookup method if
it couldn't think of anything better).
If using a legacy collection (I assume you mean Hashtable),
That's one of them. There are more custom collections in the framework than
you can shake a stick at, actually, some of which don't even implement
IEnumerable (but let's politely ignore those).
then the proper approach is to obtain an IDictionaryEnumerator from it
explicitly, and use that.
This works for Hashtable; it doesn't work for (say) NameObjectCollectionBase
and derivates, which return an enumerator over the keys only. If you *can*
obtain an enumerator that obtains the values as pairs, then yes, by all
means use that in preference to any of these approaches.

--
J.
Jul 9 '08 #5
On Jul 9, 8:19*am, "Marc Gravell" <marc.grav...@gmail.comwrote:
Re making it readable... perhaps an extension method (or take of the "this"
in C# 2 to get a static helper method) to walk the two in parallel;
something like below; this could be used i.e.
<snip>

FWIW, Eric Lippert mentioned that MS effectively "missed" an operator
for LINQ here - the "Zip" operator. who knows, it may even get
implemented in a future version.

Of course, there are options here in terms of what should happen when
the left or right sequence ends before the other one does - it could
through an exception, return pairs with the default value for the
type, or just end abruptly (as yours does).

Candidate for MiscUtil, perhaps?

Jon
Jul 9 '08 #6
On Jul 9, 6:52*pm, "Jon Skeet [C# MVP]" <sk...@pobox.comwrote:
On Jul 9, 8:19*am, "Marc Gravell" <marc.grav...@gmail.comwrote:
Re making it readable... perhaps an extension method (or take of the "this"
in C# 2 to get a static helper method) to walk the two in parallel;
something like below; this could be used i.e.

<snip>

FWIW, Eric Lippert mentioned that MS effectively "missed" an operator
for LINQ here - the "Zip" operator. who knows, it may even get
implemented in a future version.
For a laugh, here's a LINQ 1-liner that seems to do that:

xs.Select((x, i) =new { x = x, i = i }).Join(ys.Select((y, i) =new
{ y = y, i = i }), xi =xi.i, yi =yi.i, (xi, yi) =new { xi.x,
yi.y })

Performance-wise, of course, this is so bad it's not even a contender.
Jul 10 '08 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
by: Phil | last post by:
Hi, I read somewhere that the new version (v1.1) has improved the performance of 'foreach' over 'for'. Is that true? I did some measurements and I still think for has an upperhand... ? Phil
104
by: cody | last post by:
What about an enhancement of foreach loops which allows a syntax like that: foeach(int i in 1..10) { } // forward foeach(int i in 99..2) { } // backwards foeach(char c in 'a'..'z') { } // chars...
27
by: Tripper | last post by:
Which is the better way to go and why? //trivial example List<string> strings = GetStrings(); foreach (string s in strings) { // some operation; } strings.ForEach(
43
by: parallelpython | last post by:
Has anybody tried to run parallel python applications? It appears that if your application is computation-bound using 'thread' or 'threading' modules will not get you any speedup. That is because...
0
by: modularmix | last post by:
Does anyone know how to run the Excel Macro for two different spreadsheets in parallel. Here is the code that works sequentially. Workbooks.Open Filename:="C:\Documents and...
2
by: modularmix | last post by:
Does anyone know the code for running the Excel Macro for two different spreadsheets in parallel. Here is the code that works for them sequentially. Workbooks.Open Filename:="C:\Documents and...
10
by: fig000 | last post by:
HI, I'm new to generics. I've written a simple class to which I'm passing a generic list. I'm able to pass the list and even pass the type of the list so I can use it to traverse it. It's a...
1
by: ssndk123 | last post by:
Hi, Using the UserPort program that changes permissions in XP so that I am able to write directly to the parallel port using assembler.. I'm trying to send out square wave pulses for x number...
8
by: Bill Butler | last post by:
"raylopez99" <raylopez99@yahoo.comwrote in message news:bd59f62a-5b54-49e8-9872-ed9aef676049@t54g2000hsg.googlegroups.com... <snip> I don't think "right" is the correct word. There are many...
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 4 Oct 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM) The start time is equivalent to 19:00 (7PM) in Central...
0
tracyyun
by: tracyyun | last post by:
Hello everyone, I have a question and would like some advice on network connectivity. I have one computer connected to my router via WiFi, but I have two other computers that I want to be able to...
2
by: giovanniandrean | last post by:
The energy model is structured as follows and uses excel sheets to give input data: 1-Utility.py contains all the functions needed to calculate the variables and other minor things (mentions...
4
NeoPa
by: NeoPa | last post by:
Hello everyone. I find myself stuck trying to find the VBA way to get Access to create a PDF of the currently-selected (and open) object (Form or Report). I know it can be done by selecting :...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 1 Nov 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM) Please note that the UK and Europe revert to winter time on...
0
NeoPa
by: NeoPa | last post by:
Introduction For this article I'll be focusing on the Report (clsReport) class. This simply handles making the calling Form invisible until all of the Reports opened by it have been closed, when it...
0
isladogs
by: isladogs | last post by:
The next online meeting of the Access Europe User Group will be on Wednesday 6 Dec 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, Mike...
4
by: GKJR | last post by:
Does anyone have a recommendation to build a standalone application to replace an Access database? I have my bookkeeping software I developed in Access that I would like to make available to other...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.