2009-04-15 19 views
9

私はHaskellからintersperse functionを学び、C#の実装を探していました。Enumerable.Intersperseの拡張メソッドですか?

Intersperseは2つの引数、IEnumerable <T>ソースとT要素をとります。これは、sourceの各要素の間に挿入された要素を持つ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

ああに1を持っています!私にそれを打つ! – Daniel

+0

確かに、その中の秒... –

+0

あなたの意見は理にかなっていますが、私はあなたの答えによって混乱しています。あなたの例では、散在しているアイテムが最初に来ると思われますが、それは正しいとは思えません。 –

-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

多くの "値" の –

5

私はLinqソリューションの精神の中で、怠惰なソリューションをコーディングしました!私が思いついた他の解決策は、データを返す前にリスト全体をトラバースし、結果リストを返すことでした。

その他の回答には、ループの繰り返しごとにifチェックがあります。

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()を使うときは、イテレータ –

+0

@MarcをDispose()する必要があります。 – Daniel

+2

コレクションが大きい場合に分岐を削除するのは良いことです。ところで、これは古典的な "フェンスのポスト問題"です。ここでn + 1やn-1のものが必要です。 'String.Join()'は、C#ersがこれらと接触する最も一般的な方法です。 –

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; 
    } 
}