views:

127

answers:

5

I need to prepend a single value to an IEnumerable (in this case, IEnumerable<string[]>). In order to do that, I'm creating a List<T> just to wrap the first value so that I can call Concat:

// get headers and data together
IEnumerable<string[]> headers = new List<string[]> {
    GetHeaders()
};
var all = headers.Concat(GetData());

Yuck. Is there a better way? And how would you handle the opposite case of appending a value?

+5  A: 

Use the Enumerable.Concat extension method. For appending values instead of prepending, you'd just call Concat in reverse. (ie: GetData().Concat(GetHeaders());)

If GetHeaders() returns a single string array, I'd personally probably wrap it in a single element array instead of a list:

 var all = (new[] {GetHeaders()}).Concat(GetData());
Reed Copsey
GetHeaders() returns `string[]`, GetData() returns `IEnumerable<string>`. Did you read my question?
Gabe Moothart
@Gabe: This will work with string[] and IEnumerable<string> - arrays implement IEnumerable<T>. If your string[] is **string**, however, things are a bit different. Your question wasn't incredibly clear here.
Reed Copsey
@Reed right, I commented before I say your edit
Gabe Moothart
@Gabe: I'm still not sure exactly what you want - I put in another edit, that shows you how to preserve all elements as arrays...
Reed Copsey
@Reed and my comment was wrong - GetData() returns `IEnumerable<string[]>`, sorry for the confusion. You should be able to infer the types from my question, though.
Gabe Moothart
@Gabe: My original edit should work, then ;) Stripped out everything else...
Reed Copsey
+11  A: 

I wrote custom extension methods to do this:

public static IEnumerable<T> Append<T>(this IEnumerable<T> source, T item)
{
    foreach (T i in source)
        yield return i;

    yield return item;
}

public static IEnumerable<T> Prepend<T>(this IEnumerable<T> source, T item)
{
    yield return item;

    foreach (T i in source)
        yield return i;
}

In your scenario, you would write:

var all = GetHeaders().Append(GetData());

As chilltemp commented, this does not mutate the original collection. In true Linq fashion, it generates a new IEnumerable<T>.

Greg
Nice! I have some in my library just like those.
kbrimington
Elegant. It should be noted that this will return a new IEnumerable<T> by enumerating the existing collection. It does not actually append/prepend the original collection.
chilltemp
A: 

Rx contains StartWith method that prepends value to sequence. Also Return can wrap value as sequence so it can be appended via Concat.

        var c = new[] {4};
        var c1 = c.StartWith(1, 2, 3);
        var c2 = c1.Concat(EnumerableEx.Return(5));

        c2.Run(Console.Write); // 12345
desco
A: 

To prepend, why not say:

IEnumerable<object> r;
r.ToList().Insert(0, null);
Adam
A: 

Another option is a helper method that creates a sequence out of a single item:

public static class EnumerableExt
{
    public static IEnumerable<T> One<T>(T item)
    {
        yield return item;
    }
}

...
//prepend:
EnumerableExt.One( GetHeaders() ).Concat( GetData() );

//append:
GetData().Concat( EnumerableExt.One( GetHeaders() );
Gabe Moothart