Andrew Florko
Andrew Florko

Reputation: 7750

Shortest way to create class instances when properties are populated from sequential data

I have list of strings

var data = new List<string> {"Name1", "Surname1", "Name2", "Surname2" };

and class that describes Person

class Person
{
   public string Name { get; set; }
   public string Surname { get; set; }
}

What is the shortest way to create List<Person> populated from data list The result should be equal to

var persons = new List<Person>
{ 
    new Person { Name = "Name1", Surname = "Surname1" }, 
    new Person { Name = "Name2", Surname = "Surname2" }
};

Thank you in advance!

Upvotes: 2

Views: 509

Answers (2)

Dean Chalk
Dean Chalk

Reputation: 20471

If you wanted to make this kind of function a little more generic (maybe tomorrow Person will take 3 values), you could create an extension method to return chunks of data:

public static List<List<T>> GetChunks<T>(this IList<T> list, int chunkSize)
{
    return Enumerable
                .Range(0, list.Count / chunkSize)
                .Select(i => Enumerable
                    .Range(0, chunkSize)
                    .Select(j => list[i * chunkSize + j])
                    .ToList())
                .ToList();
}

then in this situation we could do the following:

var people = data.GetChunks(2)
    .Select(s => new Person() { Name = s[0], Surname = s[1] });

Upvotes: 2

Ani
Ani

Reputation: 113452

If you can use LINQ, here's one way:

 var persons = Enumerable.Range(0, data.Count / 2)
                         .Select(i => new Person
                                          {
                                             Name = data[2 * i],
                                             Surname = data[2 * i + 1] 
                                          })
                         .ToList();

You can view this as loosely equivalent to:

var persons = new List<Person>();

for(int i = 0; i < data.Count / 2 ; i++)
{
   var person = new Person
                    {
                       Name = data[2 * i],
                       Surname = data[2 * i + 1] 
                    };

   persons.Add(person);
}

Here's another, less efficient, version (works only on .NET 4.0) that uses the Zipoperator:

var names = data.Where((s, i) => i % 2 == 0);
var surnames = data.Where((s, i) => i % 2 == 1);

var persons = names.Zip(surnames,
                        (name, surname) => new Person
                                           { 
                                              Name = name, 
                                              Surname = surname
                                           })
                   .ToList();

You could also use the Batchoperator from MoreLinq here:

var persons = data.Batch(2)
                  .Select(pair => new Person
                                      { 
                                         Name = pair.ElementAt(0), 
                                         Surname = pair.ElementAt(1)
                                      })
                  .ToList();

Upvotes: 6

Related Questions