473,407 Members | 2,315 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,407 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 5117
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
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

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.