LINQ-запрос, сравниваемый с несколькими - PullRequest
0 голосов
/ 23 февраля 2012

ОБНОВЛЕНО: Извинения, мой коллега немного обновил модель

ОБНОВЛЕНО: Учитывая контекст этой идеи, возможно, это поможет

У меня естьсписок ShowData для шоу.Каждый ShowData содержит несколько отпечатков.Итак,

1 Show -> Many ShowData -> Many Prints

У меня есть два набора данных обоих объектов одного типа - ShowData

Отпечаток пальца выглядит следующим образом:

public class ShowData
{
    public ShowData() { }        
    public int time { get; set; }
    public List<Prints> prints { get; set; }
}
public class Prints
{
    public Prints() { }        
    public int value { get; set; }
    public string range { get; set; }
}

Я получаю все ShowData для определенного шоу:

var ShowData1 = (from showData1 in context.ShowDatas
                                where (showData1.Show.Id == 1)                                    
                                select new
                                {
                                    showData = showData1,
                                    prints = showData1.Prints
                                });                  

Так что пример:

DATASET A

time      prints
1         {1,low},{4,low},{8,low},{9,low},{10,low},{11,high},{15,high},{16,high},{18,high}
2         {4,low},{7,low},{8,low},{9,low},{10,low},{12,high},{15,high},{16,high},{19,high}
3         {1,low},{2,low},{3,low},{8,low},{9,low},{11,high},{12,high},{15,high},{16,high}
4         {1,low},{7,low},{8,low},{9,low},{10,low},{11,high},{12,high},{14,high},{15,high}
5         {1,low},{5,low},{6,low},{8,low},{9,low},{11,high},{14,high},{17,high},{19,high}

DATASET B

time      prints
1         {1,low},{2,low},{3,low},{4,low},{5,low},{11,high},{12,high},{13,high},{18,high}
2         {0,low},{3,low},{5,low},{6,low},{7,low},{11,high},{13,high},{19,high},{20,high}

Первый набор данных (DATASET A) составляет примерно 4000 элементов ShowData.У меня есть другой набор данных ShowData, который имеет длину около 120 элементов (DATASET B).

Я пытаюсь найти способ сравнить два списка, чтобы выявить все time точек, гдеотпечатки в DATASET B имеют по крайней мере 2 совпадения с отпечатками в DATASET A. Однако должно быть как минимум 2 совпадения для низкого и 2 совпадения для высокого

Таким образом, мой возвращенный запрос может выглядеть следующим образом:

TimeInDataSetB         TimesInDataSetAForLows      TimeInDataSetAForHighs
1                              1,3,5                       3,4
2                                                           5

Итак, выше, у печати (с диапазоном = низкий уровень) в момент времени 1 в наборе данных D было как минимум 2 совпадения с отпечатками, расположенными в моменты времени 1,3,5 в DatasetA И для печати (с диапазоном = высокий) в момент времени 1 в DatasetB было как минимум 2 совпадения с отпечатками, расположенными в моментах 3,4 в DatasetA.

Элемент во время 2 в DataSetB не имеет совпадений ни для одногов DataSet для минимумов и только 1 совпадение для максимумов

Может кто-нибудь помочь с этим?(я ищу ответ в c #)

Используя метод, описанный в первом ответе, я попробовал следующее:

var query3 = from a in recordingPoints
                             from b1 in ShowData1
                             let timeIntersects = a.Prints.Intersect(b1.prints, printsEqualityComparer)
                             where timeIntersects.GroupBy(x => x.Range)
                                                 .All(x => x.Count() > 2)
                             group b1 by a.Time into grouped
                             select new
                             {

                                 TimeInDataSetA = grouped.Key,
                                 TimeInDataSetB = grouped.ToArray()
                             };

, где recordingPoints - это список ShowData

ДАННЫЕ ДЛЯ ИСПЫТАНИЯ С

List<ShowData> bigdataset = new List<Ent.ShowData>();
                List<ShowData> smalldataset = new List<Ent.ShowData>();

                List<int> ints = new List<int>(new int[]{1, 4, 8, 9, 10, 11, 15, 16, 18});
                ShowData od = new Ent.ShowData();
                od.Show.Id = 7;
                foreach (int it in ints)
                {
                    Prints pr = new Prints();
                    if (it < 11)
                        pr.Range = "low";
                    else
                        pr.Range = "high";
                    pr.Value = it.ToString();
                    od.Prints.Add(pr);
                }                    
                od.Time = 1;
                bigdataset.Add(od);

                ints = new List<int>(new int[] { 4, 7, 8, 9, 10, 12, 15, 16, 19 });
                od = new Ent.ShowData();
                od.Show.Id = 7;
                foreach (int it in ints)
                {
                    Prints pr = new Prints();
                    if (it < 11)
                        pr.Range = "low";
                    else
                        pr.Range = "high";
                    pr.Value = it.ToString();
                    od.Prints.Add(pr);
                }
                od.Time = 2;
                bigdataset.Add(od);

                ints = new List<int>(new int[] { 1, 2, 3, 8, 9, 11, 12, 15, 16 });
                od = new Ent.ShowData();
                od.Show.Id = 7;
                foreach (int it in ints)
                {
                    Prints pr = new Prints();
                    if (it < 11)
                        pr.Range = "low";
                    else
                        pr.Range = "high";
                    pr.Value = it.ToString();
                    od.Prints.Add(pr);
                }
                od.Time = 3;
                bigdataset.Add(od);

                ints = new List<int>(new int[] { 1, 7, 8, 9, 10, 11, 12, 14, 15 });
                od = new Ent.ShowData();
                od.Show.Id = 7;
                foreach (int it in ints)
                {
                    Prints pr = new Prints();
                    if (it < 11)
                        pr.Range = "low";
                    else
                        pr.Range = "high";
                    pr.Value = it.ToString();
                    od.Prints.Add(pr);
                }
                od.Time = 4;
                bigdataset.Add(od);

                ints = new List<int>(new int[] { 1, 5, 6, 8, 9, 11, 14, 17, 19 });
                od = new Ent.ShowData();
                od.Show.Id = 7;
                foreach (int it in ints)
                {
                    Prints pr = new Prints();
                    if (it < 11)
                        pr.Range = "low";
                    else
                        pr.Range = "high";
                    pr.Value = it.ToString();
                    od.Prints.Add(pr);
                }
                od.Time = 5;
                bigdataset.Add(od);

                ints = new List<int>(new int[] { 1, 2, 3, 4, 5, 11, 12, 13, 18 });
                od = new Ent.ShowData();
                foreach (int it in ints)
                {
                    Prints pr = new Prints();
                    if (it < 11)
                        pr.Range = "low";
                    else
                        pr.Range = "high";
                    pr.Value = it.ToString();
                    od.Prints.Add(pr);
                }
                od.Time = 1;
                smalldataset.Add(od);

                ints = new List<int>(new int[] { 0, 3, 5, 6, 7, 11, 13, 19, 20 });
                od = new Ent.ShowData();
                foreach (int it in ints)
                {
                    Prints pr = new Prints();
                    if (it < 11)
                        pr.Range = "low";
                    else
                        pr.Range = "high";
                    pr.Value = it.ToString();
                    od.Prints.Add(pr);
                }
                od.Time = 2;
                smalldataset.Add(od);

var printsEqualityComparer = new PrintsEqualityComparer();

                    var query4 = from a in smalldataset
                                 from b1 in bigdataset
                                 let timeIntersects = a.Prints.Intersect(b1.Prints, printsEqualityComparer)
                                 where timeIntersects.GroupBy(x => x.Range)
                                                     .All(x => x.Count() > 1)
                                 group b1 by a.Time into grouped
                                 select new
                                 {
                                     TimeInDataSetA = grouped.Key,
                                     TimeInDataSetB = grouped.ToArray()
                                 };

1 Ответ

3 голосов
/ 23 февраля 2012

Вы можете выполнить пересечение для каждого элемента в B над каждым элементом в A, отфильтровывая минимальное совпадение 3 и группируя по времени, установленному в A, как:

var query = from a in listA
            from b in listB
            where a.prints.Intersect(b.prints).Count() >= 3
            group b by a.time into grouped
            select new
            {
                TimeInDataSetA = grouped.Key,
                TimeInDataSetB = grouped.ToArray()
            };

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

// please see: http://blogs.msdn.com/b/ericlippert/archive/2011/02/28/guidelines-and-rules-for-gethashcode.aspx
class PrintsEqualityComparer : IEqualityComparer<Prints>
{
    public bool Equals(Prints x, Prints y)
    {
        return object.Equals(x, y) && object.Equals(x.value, y.value);
    }

    public int GetHashCode(Prints obj)
    {
        return obj.range.GetHashCode() ^ obj.value.GetHashCode();
    }
}
var printsEqualityComparer = new PrintsEqualityComparer();

var query = from a in listA
        from b in listB
        let timeIntersects = a.prints.Intersect(b.prints, printsEqualityComparer)
        where timeIntersects.GroupBy(x => x.range)
                            .All(x => x.Count() > 2)
        group b by a.time into grouped
        select new
        {
            TimeInDataSetA = grouped.Key,
            TimeInDataSetB = grouped.ToArray()
        };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...