2011-12-31 2 views
2

У меня есть существующая коллекция объектов с двумя интересными свойствами. Оба свойства одного типа. Я хочу создать новую последовательность, состоящую из значений свойств. Вот один из способов (я использую кортежи вместо моего пользовательского типа для простоты):Создать последовательность, состоящую из нескольких значений свойств

var list = new List<Tuple<string, string>> 
    { Tuple.Create("dog", "cat"), Tuple.Create("fish", "frog") }; 

var result = 
    list.SelectMany(x => new[] {x.Item1, x.Item2}); 

foreach (string item in result) 
{ 
    Console.WriteLine(item); 
} 

Результаты в:

dog 
cat 
fish 
frog

Это дает мне результаты, которые я хочу, но есть лучший способ выполнить это (в частности, без необходимости создания массивов или коллекций)?

Edit:

Это также работает, за счет итерация коллекции дважды:

var result = list.Select(x => x.Item1).Concat(list.Select(x => x.Item2)); 
+0

Что такое «результат [вы] хотите»? Имеет зубчатый массив? Создание списка анонимных типов? ... –

+0

Если вы указали очевидное, вы можете сделать «var result = new [] {« dog »,« cat »,« fish »,« frog »};« Но если вы должны начать со списка кортежей, то, что у вас отлично выглядит. –

+0

@jmh_gr - Я только что редактировал вопрос для ясности. Я хочу 'IEnumerable ', состоящий из 'originalListFirstItem.StringProperty1',' originalListFirstItem.StringProperty2', 'originalListSecondItem.StringProperty1',' originalListSecondItem.StringProperty2' и т. Д. – TrueWill

ответ

2

Если вы хотите избежать создания другой коллекции, вы можете дать результаты вместо этого.

void Main() 
{ 
    var list = new List<Tuple<string, string>> 
     { Tuple.Create("dog", "cat"), Tuple.Create("fish", "frog") }; 

     foreach (var element in GetSingleList(list)) 
     { 
      Console.WriteLine (element); 
     } 
} 

// A reusable extension method would be a better approach. 
IEnumerable<T> GetSingleList<T>(IEnumerable<Tuple<T,T>> list) { 

    foreach (var element in list) 
    { 
     yield return element.Item1; 
     yield return element.Item2; 
    } 

} 
+0

* Очень * хорошо. Я принимаю это как (а) он не создает новые массивы/коллекции и (б) он только итерации над исходной коллекцией один раз. Тип параметра может быть также «IEnumerable >». – TrueWill

+0

@TrueWill - я обновил свой ответ. –

2

Я думаю, что ваш подход хорошо, и я бы придерживаться этого. Использование массива прекрасно выполняет свою работу при использовании SelectMany, а конечным результатом является IEnumerable<string>.

Есть несколько альтернативных подходов, но я думаю, что они более подробные, чем ваш подход.

Aggregate подход:

var result = list.Aggregate(new List<string>(), (seed, t) => 
{ 
    seed.Add(t.Item1); 
    seed.Add(t.Item2); 
    return seed; 
}); 
result.ForEach(Console.WriteLine); 

ForEach подход:

var result = new List<string>(); 
list.ForEach(t => { result.Add(t.Item1); result.Add(t.Item2); }); 
result.ForEach(Console.WriteLine); 

В обоих случаях новый List<string> создается.

+1

+1, особенно для гениального использования Aggregate! – TrueWill

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