By B.Balamanigandan


2016-09-14 07:41:07 8 Comments

I'm having a List<List<string>>, which is return from the remote data source (i.e., WCF). So, I need to modify the following data into a user-friendly list using LINQ

The C# Code is

List<List<string>> PersonInfo = new List<List<string>>()
{
    new List<string>() {"John", "Peter", "Watson"},
    new List<string>() {"1000", "1001", "1002"}
}

Appropriate Screen Shot: Existing

enter image description here

I need to rotate the data as like the below Screenshot: Proposed

enter image description here

Kindly assist me how to rotate the data using LINQ C#

6 comments

@andredking 2018-07-22 18:23:04

This extends the Zip idea above to any number of lists. Zip will truncate the row lists to the smallest rank.

List<List<string>> PersonInfo = new List<List<string>>()
{
    new List<string>() {"John", "Peter", "Watson"},
    new List<string>() {"1000", "1001", "1002"},
    new List<string>() {"2000", "2001", "2002"},
    new List<string>() {"3000", "3001", "3002"}
};

var seed = Enumerable.Empty<List<string>>();
var transformed = PersonInfo.Aggregate(seed, (acc, r) =>
   acc.Any()
 ? acc.Zip(r, (row, nextElement) => { row.Add(nextElement); return row; })
 : r.Select(e => new List<string> { e }) //initialize target list using first row
); 

@Tim Schmelter 2016-09-14 08:14:05

You can use Enumerable.Range and Enumerable.ElementAtOrDefault:

List<List<string>> rotated = Enumerable.Range(0, PersonInfo.Max(list => list.Count))
 .Select(i => PersonInfo.Select(list => list.ElementAtOrDefault(i)).ToList())
 .ToList();

PersonInfo.Max(list => list.Count) returns the max-size of the lists. This will be the new size of the main list, in this case 3. Enumerable.Range is like a for-loop. For every list it will now select all strings at these indexes. If the sizes are different you'll get null(because of ElementAtOrDefault).

If the lists had the same size you can apply the same query to get the original list back:

PersonInfo = Enumerable.Range(0, rotated.Max(list => list.Count))
 .Select(i => rotated.Select(list => list.ElementAtOrDefault(i)).ToList())
 .ToList();

As extension:

public static IEnumerable<IList<T>> Rotate<T>(this IEnumerable<IList<T>> sequences)
{
    var list = sequences as IList<IList<T>> ?? sequences.ToList();
    int maxCount = list.Max(l => l.Count);
    return Enumerable.Range(0, maxCount)
        .Select(i => list.Select(l => l.ElementAtOrDefault(i)).ToList());
}

Usage:

IEnumerable<IList<string>> rotated = PersonInfo.Rotate();
IEnumerable<IList<string>> rotatedPersonInfo = rotated.Rotate(); // append ToList to get the original list

@Tim Schmelter 2016-09-14 08:33:50

@Oliver: why delete? Of course the lists must have the same size, but that is the case here. But thanks for noting, I've fixed my answer

@Oliver 2016-09-14 08:45:49

I read it as Min not Max (duh) so I was referring to data loss rather than additional values. Different none the less!

@Oliver 2016-09-14 08:06:41

This is a simple and flexible solution, it will handle multiple inner lists with any number of dimensions.

List<List<string>> PersonInfo = new List<List<string>>()
{
    new List<string>() {"John", "Peter", "Watson"},
    new List<string>() {"1000", "1001", "1002"}
};


var result = PersonInfo
    .SelectMany(inner => inner.Select((item, index) => new { item, index }))
    .GroupBy(i => i.index, i => i.item)
    .Select(g => g.ToList())
    .ToList();

@pmackni 2020-02-11 21:35:51

I realize this might revive this thread, but being not wholly familiar with this segment of VB.net, I was wondering if it would be possible to interject a Nothing or similar placeholder value if the input lists are uneven?

@Oliver 2020-02-12 09:08:32

@pmackni That's entirely possible. I'd say it's worth a separate question though - how you can convert a jagged array to a rectangular array, filling gaps with a specific value.

@Dennis_E 2016-09-14 08:01:12

Assuming there are only ever 2 lists inside PersonInfo:

var rotated = PersonInfo[0]
    .Zip(PersonInfo[1], (a, b) => new List<string> { a, b }).ToList();

If there can be any number of Lists inside of PersonInfo:

Enumerable.Range(0, PersonInfo[0].Count)
    .Select(i => PersonInfo.Select(lst => lst[i]).ToList()).ToList();

@fubo 2016-09-14 08:04:25

Here is a extension method

public static IEnumerable<IEnumerable<T>> Pivot<T>(this IEnumerable<IEnumerable<T>> source)
{
    var enumerators = source.Select(e => e.GetEnumerator()).ToArray();
    try
    {
        while (enumerators.All(e => e.MoveNext()))
        {
            yield return enumerators.Select(e => e.Current).ToArray();
        }
    }
    finally
    {
        Array.ForEach(enumerators, e => e.Dispose());
    }
}

so you can

var result = PersonInfo.Pivot();

@sachin 2016-09-14 07:59:52

Try this:

List<List<string>> PersonInfo = new List<List<string>>(){
new List<string>() {"John", "Peter", "Watson"},
new List<string>() {"1000", "1001", "1002"}};

List<List<string>> PivitedPersonInfo = new List<List<string>>();
for (int i = 0; i < PersonInfo.First().Count; i++)
{
    PivitedPersonInfo.Add(PersonInfo.Select(x => x.ElementAt(i)).ToList());
}

Related Questions

Sponsored Content

11 Answered Questions

[SOLVED] Concat all strings inside a List<string> using LINQ

  • 2009-02-18 00:56:57
  • Jobi Joy
  • 423954 View
  • 544 Score
  • 11 Answer
  • Tags:   c# linq .net-3.5

10 Answered Questions

[SOLVED] Group by in LINQ

  • 2011-09-06 19:44:20
  • test123
  • 1320001 View
  • 1069 Score
  • 10 Answer
  • Tags:   c# linq group-by

11 Answered Questions

[SOLVED] What are the correct version numbers for C#?

64 Answered Questions

[SOLVED] What is the difference between String and string in C#?

13 Answered Questions

[SOLVED] Multiline string literal in C#

  • 2009-07-08 20:03:34
  • Chet
  • 636309 View
  • 1064 Score
  • 13 Answer
  • Tags:   c# string shorthand

23 Answered Questions

[SOLVED] LINQ query on a DataTable

39 Answered Questions

25 Answered Questions

[SOLVED] Case insensitive 'Contains(string)'

14 Answered Questions

[SOLVED] Using LINQ to remove elements from a List<T>

  • 2009-05-12 15:56:24
  • TK.
  • 621492 View
  • 661 Score
  • 14 Answer
  • Tags:   c# .net linq list

7 Answered Questions

[SOLVED] Multiple "order by" in LINQ

  • 2008-11-18 13:34:11
  • Sasha
  • 609125 View
  • 1592 Score
  • 7 Answer
  • Tags:   linq sql-order-by

Sponsored Content