Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combining collections of different types with LINQ

Tags:

c#

linq

Let's say I have these 2 arrays:

const int length = 5;
var ints = new int[length] { 1, 2, 3, 4, 5 };
var strings = new string[length] { "s1", "s2", "s3", "s4", "s5" };

I want to loop over these and instead of this

for (var index = 0; index < length; index++)
{
    var i = ints[index];
    var s = strings[index];
    DoSomething(i, s);
}

I wonder if I, using LINQ, could somehow achieve something like this

var items = ... i in ints
            ... s in strings
            select new { I = i, S = s };

foreach (var item in items)
{
    DoSomething(item.I, item.S);
}

Just doing a nested from like this doesn't work

var items = from i in ints
            from s in strings
            select new { I = i, S = s };

since that will repeat the inner from for each outer iteration.

like image 616
Johann Gerell Avatar asked Apr 20 '14 00:04

Johann Gerell


People also ask

What collections can LINQ be used with?

You can use LINQ to query any enumerable collections such as List<T>, Array, or Dictionary<TKey,TValue>. The collection may be user-defined or may be returned by a . NET API.

Can we use LINQ on ArrayList in C#?

LINQ with ArrayList You don't need to specify array size unlike traditional array and the size grows as you will add more element into it. However, it is slower than Array but it is more useful when you work with collection. Here, in this example, we will learn how to process data in ArrayList using LINQ C#.

Can LINQ query work with Array?

Yes it supports General Arrays, Generic Lists, XML, Databases and even flat files. The beauty of LINQ is uniformity.

What is LINQ in which scenarios it should be used?

LINQ in C# is used to work with data access from sources such as objects, data sets, SQL Server, and XML. LINQ stands for Language Integrated Query. LINQ is a data querying API with SQL like query syntaxes. LINQ provides functions to query cached data from all kinds of data sources.


4 Answers

As suggested by @CharlesNRice, you can use LINQ Zip like this :

var items = ints.Zip(strings, (i, s) => new {I = i, S = s});
like image 135
har07 Avatar answered Sep 30 '22 04:09

har07


You want linq Zip. For example check this site http://jesseliberty.com/2011/06/13/the-linq-zip-operator/

I'm still going to add an example just to point something out. Zip will always goes to the shortest length. Even with the ints at 6 it will still return back just 5. I know in your example you had them the same but just passing on information about linq's Zip.

var ints = new int[] { 1, 2, 3, 4, 5, 6 };
var strings = new string[] { "s1", "s2", "s3", "s4", "s5" };
var zipper = ints.Zip(strings, (i, s) => new {i, s});
like image 36
CharlesNRice Avatar answered Sep 27 '22 04:09

CharlesNRice


I see people creating a new object but no one is showing how to invoke DoSomething.

I believe this is what you want:

ints.Zip(strings, (i,s) => DoSomething(i,s));

As Grant points out you would need the following if DoSomething returns void:

ints.Zip(strings, (i,s) => { DoSomething(i,s); return 0;} );

It is also important to remember that Linq is lazy! Nothing will happen before you actually cause this code to run. So for example:

var a = ints.Zip(strings, (i,s) => { DoSomething(i,s); return 0;} );

Will not cause DoSomething to be called. However

a.ToList();

or

a.Count();

Will cause DoSomething to be called for all values.

You could also just add ToList() or Count() to the end of the first statement, so this is the best answer to your question:

ints.Zip(strings, (i,s) => { DoSomething(i,s); return 0;} ).Count();
like image 28
Hogan Avatar answered Sep 29 '22 04:09

Hogan


This can also be done using Select method:

ints.Select((x,idx) => new { I = x, S = strings[idx] });
like image 41
Selman Genç Avatar answered Sep 28 '22 04:09

Selman Genç