Объединяя Xs, Ys в очки с Linq - PullRequest
2 голосов
/ 21 июня 2010

Я, кажется, немного застрял в этом, но мой опыт в Linq невелик. В принципе, у меня есть что-то вроде этого кода:

public class Point
{
    public int X { get; set; }
    public int Y { get; set; }
}

public class B
{
    public List<Point> Points { get; set; }
    public B(IEnumerable<int> Xs, IEnumerable<int> Ys)
    {
        // How to best combine Xs and Ys into Points ?
    }
}

Теперь, как мне заполнить этот конструктор, чтобы правильно объединить эти коллекции? Я бы обычно использовал .Join(), но нет внутреннего ключа для присоединения. Он также должен иметь возможность обрабатывать случайный случай, когда в одном массиве меньше элементов, чем в другом, или он пуст (никогда не должно быть, но это возможно).

Ответы [ 2 ]

4 голосов
/ 21 июня 2010

В C # 4 вы можете использовать оператор Zip :

var result = Xs.Zip( Ys, (a,b) => new Point(a,b) );

В C # 3 вы можете использовать ElementAt в одной из последовательностей с помощью select, чтобы сделать то же самое:

var result = Xs.Select( (x,i) => new Point( x, Ys.ElementAt(i) );

Основная проблема со вторым вариантом заключается в том, что ElementAt может быть очень дорогим, если коллекция IEnumerable сама является проекцией (в отличие от чего-то, что реализует собственные операции индексации, такие как массив).или список).Вы можете обойти это, сначала заставив вторую коллекцию быть списком:

var YsAsList = Ys.ToList();
var result = Xs.Select( (x,i) => new Point( x, YsAsList.ElementAt(i) );

Другая проблема, с которой вам придется столкнуться (если вы не используете Zip), - это как работать с несбалансированными коллекциями.Если одна последовательность длиннее другой, вы должны решить, какое должно быть правильное разрешение.Ваши варианты:

  1. Не поддерживает это.Сбой или отмена попытки.
  2. Сжатие столько элементов, сколько существует в более короткой последовательности.
  3. Сжатие столько элементов, сколько существует в более длинной последовательности, заменяя значения по умолчанию для короткой последовательности.

Если вы используете Zip(), вы автоматически получите второй вариант, как указано в документации:

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

Последний шаг всего этого - необходимость преобразования проектоврезультат в список, чтобы назначить его вашему Points объекту.Эта часть проста, используйте метод ToList():

Points = Xs.Select( (x,i) => new Point( x, Ys.ElementAt(i) ).ToList();

или в C # 4:

Points = Xs.Zip( Ys, (a,b) => new Point(a,b) ).ToList();
1 голос
/ 21 июня 2010

Предположительно, это может быть ошибкой, если две коллекции не имеют одинаковый размер или если одна или обе являются нулевыми..

this.Points = Xs.Select( (x,i) => new Point { X = x, Y = Ys.ElementAt(i) } ).ToList();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...