2009-04-15 99 views
9

我從Haskell學到了intersperse function,並一直在尋找一個在c#中的實現。Enumerable.Intersperse的擴展方法?

Intersperse需要2個參數,一個IEnumerable <T>源和一個T元素。它返回一個IEnumerable元素插入源的每個元素之間。

一種可能的使用情況是把一個任意整數整數列表之間,例如:

// returns: {1, 0, 2, 0, 3} 
(List<int>() {1, 2, 3}).Intersperse(0); 

這是的string.join(...)的一般情況。

回答

12

東西別人已經錯過:如果你只是想在項目之間,不也是在前面還是後面,你需要做一個額外的檢查:

public static IEnumerable<T> Intersperse<T>(this IEnumerable<T> source, T element) 
{ 
    bool first = true; 
    foreach (T value in source) 
    { 
     if (!first) yield return element; 
     yield return value; 
     first = false; 
    } 
} 
+0

啊!打我吧! – Daniel 2009-04-15 19:33:24

+0

事實上,在它的秒... – 2009-04-15 19:36:41

+0

你的觀點是有道理的,但我對你的答案感到困惑。在你的例子中,穿插物品會先到達,我認爲這是不對的。 – 2009-04-15 19:37:22

-2

如果你想知道如何實現它,我會這麼做是這樣的:

public static IEnumerable<T> Intersperse<T>(this IEnumerable<T> collection, T value) 
{ 
    foreach(T item in collection) 
    { 
     yield return item; 
     yield return value; 
    } 

    yield break; 
} 
+2

這有一對多 「值」 S – 2009-04-15 19:34:02

5

我已經編寫了一個懶惰的解決方案,本着Linq解決方案!我提出的其他解決方案涉及遍歷整個列表,然後返回數據,然後返回結果列表。

一些其他的答案中有循環的每次迭代的,如果檢查。

public static IEnumerable<T> Intersperse<T>(this IEnumerable<T> source, T element) 
{ 
    using (var enumerator = source.GetEnumerator()) { 
     if (enumerator.MoveNext()) { 
      yield return enumerator.Current; 
      while (enumerator.MoveNext()) { 
       yield return element; 
       yield return enumerator.Current; 
      } 
     } 
    } 
} 
+1

使用GetEnumerator()時,您應該Dispose()迭代器 – 2009-04-15 19:34:38

+0

@Marc,謝謝指出! – Daniel 2009-04-15 19:43:24

+2

在集合很大的情況下消除分支是很好的。順便說一句,這是一個經典的「柵欄後期問題」,你需要n + 1或n-1個東西。 'String.Join()'是C#ers與這些接觸最常見的方式。 – 2014-07-09 23:27:40

2

這將是很容易寫:

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