2016-09-16 6 views
1

Je souhaite faire une copie d'un IEnumerable<T> dans lequel un seul élément d'un index donné a été remplacé par une valeur donnée.Copier IEnumerable, remplacer un élément

I définit la méthode suivante qui fait ce que je veux:

public static IEnumerable<T> ReplaceAt<T>(this IEnumerable<T> source, T item, int index) 
{ 
    foreach (T before in source.Take(index)) 
    { 
     yield return before; 
    } 

    yield return item; 

    foreach (T after in source.Skip(index + 1)) 
    { 
     yield return after; 
    } 
} 

Cependant, alors que peut-être facile à comprendre, il semble « inefficace » pour créer deux itérateurs, dont un Saute les éléments déjà prises par le premier itérateur.

Existe-t-il une meilleure façon de définir cela?

Répondre

2

Que diriez-vous:

public static IEnumerable<T> ReplaceAt<T>(this IEnumerable<T> source, T item, int index) 
{ 
    return source.Select((value, i) => index == i ? item : value); 
} 
+0

Eh bien, juste. Cette réponse earler de la guerre que le mien :) – tym32167

+0

@ tym32167 À peine, mais j'ai voté votre réponse de toute façon. ;) –

2

ne suis pas sûr efficace, mais avez-vous essayé?

public static IEnumerable<T> ReplaceAt<T>(this IEnumerable<T> source, T item, int index) 
{ 
    return source.Select((x, i) => i == index ? item : x); 
} 
+0

Whoa, deux réponses identiques dans les 10 secondes les uns des autres. :) –

+0

@MatthewWatson: D gentil – tym32167

1

Si vous voulez devenir fou, vous pouvez déroulez le foreach manuellement:

public static IEnumerable<T> ReplaceAt<T>(this IEnumerable<T> source, T item, int index) 
{ 
    int itemIndex = 0; 
    using(var iter = source.GetEnumerator()) 
    { 
     while(iter.MoveNext()) 
     { 
      yield return itemIndex++ == index ? item : iter.Current; 
     } 
    } 
} 
+0

Comment est-ce mieux que de faire la même chose en utilisant 'foreach'? C'est à dire. 'int itemIndex = 0; foreach (valeur var dans la source) { rendement return itemIndex ++ == index? item: valeur; } '. – svick

+0

@svick assez juste, ce serait à peu près le même; Je suppose que dans ma tête je suis habitué à des exemples plus nuancés, mais oui, rétrospectivement, celui-ci est assez simple –