Пересечение двух наборов (списков) данных - PullRequest
6 голосов
/ 22 декабря 2011

У меня есть два набора данных (списки сложных объектов или данные SQL - LINQ to Entities), где я пытаюсь найти пересечение двух наборов данных. В частности, пересечение свойства Complex, "HashData", как показано ниже:

SQL data

Набор слева, вероятно, будет около 10000 строк, в то время как набор справа всегда является подмножеством около 100 строк. Я понимаю, что если я отсортирую набор слева с помощью «Hashdata» при его сохранении, выполнение поиска будет намного быстрее с использованием некоторого алгоритма двоичного поиска, однако я не могу сделать это по причинам, не относящимся к вопросу.

Меньшее подмножество данных никогда не сохраняется в SQL (показано только в таблице SQL ниже для пояснения). Он представлен в List<ShowData> во время выполнения.

В данный момент я делаю жалкий цикл по данным и сопоставляю их следующим образом (где recording - это список из 100 строк, а ShowData - это список из 10000 строк):

List<ShowData> ShowData = (from showData in context.ShowDatas
                           where (showData.Show.Id == advert.Id)
                           orderby showData.HashData ascending
                           select showData).ToList();

foreach (ShowData recording in recordingPoints) {
    foreach (ShowData actual in ShowData) {
        if (recording.HashData == actual.HashData) {
        }
    }
}

В общем, я пытаюсь сделать следующее:

Возвращает список объектов ShowData (большой набор), где любые HashData (из небольшого набора) находятся в ShowData, НО в начальном запросе LINQ to Entity к БД.

Я сблизился с:

private IEnumerable<ShowData> xyz(List<ShowData> aObj, List<ShowData> bObj)
    {
        IEnumerable<string> bStrs = bObj.Select(b => b.HashData).Distinct();
        return aObj.Join(bStrs, a => a.HashData, b => b, (a, b) => a);
    }

Ответы [ 2 ]

6 голосов
/ 22 декабря 2011

Поскольку вы используете IEnumerable, вы можете использовать метод Intersect Extension вместо Join. Если вы хотите вернуть большой набор, вам нужно пересечь результат запроса большого набора с меньшим набором. Вам нужно написать IEquality Comparer, как показано здесь: http://msdn.microsoft.com/en-us/library/bb355408.aspx, чтобы сравнить ваши объекты, а затем вызвать метод расширения Intersect:

return bStrs.Intersect(aObj, new MyEqualityComparer());
1 голос
/ 23 декабря 2011

Примерно так может работать (предупреждение не проверено):

private IEnumerable<ShowData> xyz(List<ShowData> aObj, List<ShowData> bObj)
{
    return aObj.Where(sd1 => bObj.Select(sd2 => sd2.HashData).Contains(sd1.HashData));
}
...