LINQ: adding an item to every second position

so I have a list:

["item1"] ["item2"] ["item3"] 

and I want the list to be as follows:

 [""] ["item1"] [""] ["item2"] [""] ["item3"] 

A simple reverse dial gives me exactly this:

 for (int i = list.Count-1; i >= 0; i--) list.Insert(i, string.Empty); 

But I am wondering if there is a more elegant way to do this using LINQ?

+5
source share
4 answers

Here's how to do it:

 list = list.SelectMany(x => new [] { string.Empty, x }).ToList(); 

But it is worth noting that this creates unnecessary arrays. If your list is large enough, this could be a problem. Instead, I would create a new list with capacity and populate it with a loop:

 var newList = new List<string>(list.Count * 2); int j = 0; for(int i = 0; i < list.Count * 2; i++) newList.Add(i % 2 == 0 ? string.Empty : list[j++]); 

This will prevent you from resizing the list each time you add or insert elements.

+7
source

You can use the Intersperse extension method. Thus, the meaning is clear, and the code can be reused. Code taken from Extension method for Enumerable.Intersperse with a slight modification, also including an empty string in the first position.

 public static IEnumerable<T> Intersperse<T>(this IEnumerable<T> source, T element) { foreach (T value in source) { yield return element; yield return value; } } 
+11
source

You can do this using the SelectMany LINQ Extension:

 void Main() { List<String> items = new List<String>() { "1", "2", "3" }; var result = items .SelectMany(item => new String[] {"Some value", item}) .ToList(); PrintItems(result); } void PrintItems<T>(IEnumerable<T> items) { foreach(var item in items) { Console.WriteLine(item); } } 

But, as you know, this is not the most effective way.

+1
source

Another single line using aggregate:

 List<string> result = list.Aggregate(new List<string>(list.Count * 2), (a, x) => { a.Add(""); a.Add(x); return a; }); 
+1
source

Source: https://habr.com/ru/post/1206231/


All Articles