Создать последовательность, состоящую из нескольких значений свойств - PullRequest
2 голосов
/ 31 декабря 2011

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

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

Ответы [ 2 ]

2 голосов
/ 01 января 2012

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

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

}
2 голосов
/ 31 декабря 2011

Я думаю, что ваш подход в порядке, и я бы придерживался этого. Использование массива прекрасно выполняет свою работу при использовании 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>.

...