8

Possible Duplicate:
Extension method for Enumerable.Intersperse?

I have a List<string> like this:

"foo", "bar", "cat"

I want it to look like this:

"foo", "-", "bar", "-", "cat"

Is there a C# method that does that?

Community
  • 1
  • 1
fasss
  • 145
  • 1
  • 4
  • 3
    See this previous question - http://stackoverflow.com/questions/753316/extension-method-for-enumerable-intersperse [1]: http://stackoverflow.com/questions/753316/extension-method-for-enumerable-intersperse – Paige Cook Sep 15 '11 at 11:38
  • No, you'll have to write your own. – Gabe Sep 15 '11 at 11:39
  • Why do you need this? Do you want to print out the values with a - between it? Then there are probably easier ways. – RvdK Sep 15 '11 at 11:39
  • @PoweRoy: Because I like chaining string functions in one line, like `string.Trim().Split(',')[0].Intersperse("-");`. – fasss Sep 15 '11 at 12:02
  • 1
    @Paige that link contains superior answers to those found in this question – RichK Sep 15 '11 at 12:21

7 Answers7

5

You can make an extension that returns an IEnumerable<T> with interspersed items:

public static class ListExtensions {

  public static IEnumerable<T> Intersperse<T>(this IEnumerable<T> items, T separator) {
    bool first = true;
    foreach (T item in items) {
      if (first) {
        first = false;
      } else {
        yield return separator;
      }
      yield return item;
    }
  }

}

The advantage of this is that you don't have to clutter your list with the extra items, you can just use it as it is returned:

List<string> words = new List<string>() { "foo", "bar", "cat" };

foreach (string s in words.Intersperse("-")) {
  Console.WriteLine(s);
}

You can of course get the result as a list if you need that:

words = words.Intersperse("-").ToList();
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
1

Here is an implementation out of my personal toolbox. It's more general than what you require.

For your particular example, you would write

var list = new List<string> { "foo", "bar", "cat" };
var result = list.InterleaveWith(Enumerable.Repeat("-", list.Count - 1));

See it in action.

Jon
  • 428,835
  • 81
  • 738
  • 806
0

Yes, its a custom method you would write:

List<string> AddDashesToList(List<string> list)
{
    if(list.Count > 1)
    { 
        var newList = new List<string>();

        foreach(item in list)
        {
           newList.Add(item);
           newList.Add("-");
        }

        newList.RemoveAt(newList.Count-1);

        return newList;
    }
    else
    {
         return list;
    }
}
Maxim V. Pavlov
  • 10,303
  • 17
  • 74
  • 174
0
       public  List<string> GetNewList(List<string> list, string s)
    {
        var result = new List<string>();
        foreach (var l in list)
        {
            result.Add(l);
            result.Add(s);
        }
        result.RemoveAt(result.Count - 1);
        return result;
    }

you can use this method to get you list

var result =   GetNewList(str,"-");
Sergey K
  • 4,071
  • 2
  • 23
  • 34
0

Hah! I've just written something for just this purpose!

    public static IEnumerable<T> Interleave<T>(params IEnumerable<T>[] arrays)
    {
        var enumerators = arrays.Select(array => array.GetEnumerator()).ToArray();
        var finished = true;
        do
        {
            finished = true;
            foreach (var enumerator in enumerators)
            {
                if (enumerator.MoveNext())
                {
                    yield return enumerator.Current;
                    finished = false;
                }
            }
        } while (finished == false);
    }

This will interleave the specified enumerables in the order you choose. Then you just fill an enumerable with dashes and interleave that with the original array. It can do more complex things as well.

DanielOfTaebl
  • 713
  • 5
  • 13
0

A while ago I wrote an extension method for this kind of thing:

public static IEnumerable<T> 
    Join<T>(this IEnumerable<T> src, Func<T> separatorFactory)
{
    var srcArr = src.ToArray();
    for (int i = 0; i < srcArr.Length; i++)
    {
        yield return srcArr[i];
        if(i<srcArr.Length-1)
        {
            yield return separatorFactory();
        }
    }
}

You can use it as follows:

myList.Join(() => "-").ToList()
spender
  • 117,338
  • 33
  • 229
  • 351
0

EDIT:

As pointed out, my previous code results to a string not an array of strings. So here's my edited code:

var list = new List<string> { "foo", "bar", "cat" };
var result = string.Join("-", list.Select(x => x.ToString()).ToArray());
string pattern = "(-)";
string[] test = Regex.Split(result, pattern);
foreach(var str in test)
   Console.WriteLine(str);

Retained old code for comparison purposes:

 var list = new List<string> { "foo", "bar", "cat" };
 var result = string.Join("-", list.Select(x => x.ToString()).ToArray());
 Console.WriteLine(result); // prints "foo-bar-cat

Refer to this post. Cheers!

Community
  • 1
  • 1
Annie Lagang
  • 3,185
  • 1
  • 29
  • 36