2016-09-16 2 views
1

Я хочу сделать копию IEnumerable<T>, в которой один элемент по данному индексу был заменен заданным значением.Копировать IEnumerable, заменяя элемент

я определил следующий метод, который делает то, что я хочу:

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

Однако, в то время как, возможно, легко понять это кажется «неэффективным», чтобы создать два итератора, один из которых пропускает элементы, которые уже приняты первый итератор.

Есть ли лучший способ определить это?

ответ

2

Как насчет:

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

Ну, ярмарка. Этот ответ раньше, чем мой :) – tym32167

+0

@ tym32167 Едва ли, но я все равно оставил ваш ответ. ;) –

2

Не уверен, что эффективно, но вы пробовали это?

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, два идентичных ответа в течение 10 секунд друг от друга. :) –

+0

@MatthewWatson: D nice – tym32167

1

Если вы хотите, чтобы сойти с ума, вы можете раскатать foreach вручную:

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

Как это лучше, чем делать то же самое с помощью 'foreach'? То есть 'int itemIndex = 0; foreach (значение var в источнике) { yield return itemIndex ++ == index? item: value; } '. – svick

+0

@ svick справедливо, это было бы примерно одинаково; Думаю, в моей голове я привык к более тонким примерам, но да, в ретроспективе, это довольно просто –

Смежные вопросы