Поиск с Linq - PullRequest
       14

Поиск с Linq

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

У меня есть коллекция объектов, каждый со свойством int Frame. Учитывая int, я хочу найти объект в коллекции, который имеет ближайший фрейм.

Вот что я делаю до сих пор:

public static void Search(int frameNumber)
{
    var differences = (from rec in _records
                       select new { FrameDiff = Math.Abs(rec.Frame - frameNumber), Record = rec }).OrderBy(x => x.FrameDiff);

    var closestRecord = differences.FirstOrDefault().Record;

    //continue work...
}

Это здорово и все, кроме 200 000 предметов в моей коллекции, и я очень часто называю этот метод. Есть ли относительно простой, более эффективный способ сделать это?

Ответы [ 5 ]

5 голосов
/ 03 июня 2010
var closestRecord = _records.MinBy(rec => Math.Abs(rec.Frame - frameNumber));

с использованием MinBy от MoreLINQ .

3 голосов
/ 03 июня 2010

Возможно, вы захотите сохранить кадры в структуре данных, отсортированной по Frame. Затем вы можете выполнить бинарный поиск, когда вам нужно найти ближайший к данному frameNumber.

1 голос
/ 03 июня 2010

Я не знаю, буду ли я использовать LINQ для этого, по крайней мере, с заказом.

static Record FindClosestRecord(IEnumerable<Record> records, int number)
{
    Record closest = null;
    int leastDifference = int.MaxValue;

    foreach (Record record in records)
    {
        int difference = Math.Abs(number - record.Frame);
        if (difference == 0)
        {
            return record; // exact match, return early
        }
        else if (difference < leastDifference)
        {
            leastDifference = difference;
            closest = record;
        }
    }

    return closest;
}
0 голосов
/ 03 июня 2010

Может быть, вы могли бы разделить ваш большой список предметов на 5 - 10 меньших списков, которые упорядочены по их Framediff или что-то еще?

таким образом, поиск будет быстрее, если вы знаете, в каком списке вам нужно искать

0 голосов
/ 03 июня 2010

Вы можете объединить свои высказывания в одно аля:

var closestRecord = (from rec in _records
                   select new { FrameDiff = Math.Abs(rec.Frame - frameNumber), 
                   Record = rec }).OrderBy(x => x.FrameDiff).FirstOrDefault().Record;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...