views:

177

answers:

4

Occasionally I find I need to process a list by inserting a new item after each item, except the last one. Similar to how you might put a comma between each item of a list of strings.

I got fed up of coding the special case for the last (or first) item every time, so I captured the pattern in a Linq-style extension:

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

        yield return item;
    }
}

For example, this allows me to easily programatically fill a flow document with hyperlinks, but with a line-break between each one:

para.Inlines.AddRange(_recentFiles.Select(f => f.ToHyperlink())
                                  .Separate(() => new LineBreak()));

Assuming this doesn't already exist in System.Linq.Enumerable (which is what I typically discover immediately after writing something like this), the question is, what is this Separate operation on lists usually called in other functional frameworks or languages?

A: 

Sounds like doing up a zipper (British - zip), with data on the long side and the separator on the other :-)

frou
Zip is a different operation though, converting two sequences into a new sequence of tuples.
Jon Skeet
+2  A: 

It's often called Join.

Lou Franco
`Join` has a similar meaning on `String`, but already has a very different meaning in the BCL on `IEnumerable`.
Daniel Earwicker
+1 Join will be familiar to perl users too, it is less familiar to functional users, bit unfortunate. I like the intersperse name most but this is a deserving idea
ShuggyCoUk
Although it is usually a string-specific operation, there is also a String.join in Python, Ruby, and probably a few other languages, so that is definitely not a bad name for this kind of operation.
MatrixFrog
+14  A: 

Haskell: intersperse

Zip usually means a different operation (zip [a, b, c] [x, y, z] = [(a, x), (b, y), (c, z)])

Dario
Interesting - that was my guess as well for a nice name, but I didn't know it was already used in Haskell :)
Jon Skeet
Haskell and a Skeet seal of approval, why this is practically the gold standard!
Daniel Earwicker
Yes, one of Haskell's good function names (just thinking of mapM_ etc ;-))
Dario
For those interested, Zip is in the CLR 4 beta: http://msdn.microsoft.com/en-us/library/dd267698(VS.100).aspx
Daniel Earwicker
Would be somewhat nice for LINQ - similar to Haskell's parallel list comprehenions:`[ (i, x) | x <- list | i <- [1..] ]` => `From x in List Zip i in Range(1) Select Tuple(i, x)`
Dario
Yeah, we considered such a syntax for C# 4 but decided it was not a mainline enough scenario to justify the new syntax. Perhaps in a hypothetical future version.
Eric Lippert
+1  A: 

It is also called interpose in Clojure.

user> (interpose "," ["a" "b" "c"])
("a" "," "b" "," "c")
alanlcode