What is the pattern for iterating over related sets of values?

This is quite common - especially when you are trying to make your code more data-driven - you need to iterate over related collections. For example, I just finished writing a piece of code that looks like this:

string[] entTypes = {"DOC", "CON", "BAL"}; string[] dateFields = {"DocDate", "ConUserDate", "BalDate"}; Debug.Assert(entTypes.Length == dateFields.Length); for (int i=0; i<entTypes.Length; i++) { string entType = entTypes[i]; string dateField = dateFields[i]; // do stuff with the associated entType and dateField } 

In Python, I would write something like:

 items = [("DOC", "DocDate"), ("CON", "ConUserDate"), ("BAL", "BalDate")] for (entType, dateField) in items: # do stuff with the associated entType and dateField 

I do not need to declare parallel arrays, I do not need to state that my arrays are the same length, I do not need to use an index to display the elements.

I feel there is a way to do this in C # using LINQ, but I can't figure out what it could be. Is there any easy way to iterate over multiple related assemblies?

Edit:

This is a little better, I think - at least in the case where I have the luxury of manually buttoning collections when declaring and where all collections contain objects of the same type:

 List<string[]> items = new List<string[]> { new [] {"DOC", "DocDate"}, new [] {"CON", "ConUserDate"}, new [] {"SCH", "SchDate"} }; foreach (string[] item in items) { Debug.Assert(item.Length == 2); string entType = item[0]; string dateField = item[1]; // do stuff with the associated entType and dateField } 
+4
source share
5 answers

In .NET 4.0, they add the "Zip" extension method to IEnumerable, so your code might look something like this:

 foreach (var item in entTypes.Zip(dateFields, (entType, dateField) => new { entType, dateField })) { // do stuff with item.entType and item.dateField } 

For now, I find it easiest to leave it as a for loop. There are tricks by which you can reference a "different" array (using Select () overload, which provides an index, for example), but none of them are as clean as simple for an iterator.

Here's a blog post about Zip, along with a way to implement it . Must make you go in the meantime.

+3
source

Create structure?

 struct Item { string entityType; string dateField; } 

Pretty much the same as your Pythonic solution, except for the safe type.

+2
source

This is really a variation on other topics, but it will also help ...

 var items = new[] { new { entType = "DOC", dataField = "DocDate" }, new { entType = "CON", dataField = "ConUserData" }, new { entType = "BAL", dataField = "BalDate" } }; foreach (var item in items) { // do stuff with your items Console.WriteLine("entType: {0}, dataField {1}", item.entType, item.dataField); } 
+1
source

You can use a pair and a general list.

 List<Pair> list = new List<Pair>(); list.Add(new Pair("DOC", "DocDate")); list.Add(new Pair("CON", "ConUserDate")); list.Add(new Pair("BAL", "BalDate")); foreach (var item in list) { string entType = item.First as string; string dateField = item.Second as string; // DO STUFF } 

The couple is part of Web.UI, but you can easily create your own custom class or structure.

0
source

If you just want to declare inline lists, you can do this in one step:

 var entities = new Dictionary<string, string>() { { "DOC", "DocDate" }, { "CON", "ConUserDate" }, { "BAL", "BalDate" }, }; foreach (var kvp in entities) { // do stuff with kvp.Key and kvp.Value } 

If they come from other things, we have a bunch of extension methods for creating dictionaries from various data structures.

0
source

All Articles