Удалить из списка, где все элементы не включены с помощью LINQ - PullRequest
2 голосов
/ 02 февраля 2012

У меня есть общий список ItemList, где, если каждый ListID не содержит все возможные ItemIDs, я бы хотел удалить их из списка.

Я проиллюстрирую ниже урезанную версию данных:

MaxItemID = 4

ListID       ItemID       

   1            1       
   2            1 
   2            2 
   2            3
   2            4
   3            1
   3            2 
   4            1
   4            2
   4            3
   4            4
   5            1
   5            2

И вот данные, которые я хотел бы получить:

ListID       ItemID       

   2            1 
   2            2 
   2            3
   2            4
   4            1
   4            2
   4            3
   4            4

Вчера я задал похожий вопрос, касающийся только SQL, и получил ответ об использовании Exists, что было хорошо, но с тех пор я обнаружил, что максимальное количество элементов может варьироваться, и я также думаю, что предпочитаю использовать linq. Я думал, что использование техники distinct().Count() может сработать, но пока безуспешно, и, похоже, это тоже не самый эффективный способ.

Большое спасибо

Ответы [ 4 ]

2 голосов
/ 02 февраля 2012

Попробуйте это

var query = from baseItem in itemList
    group baseItem by baseItem.ListID into gr
    where gr.Count() == MaxItemID
    join selectItem in itemList on gr.Key equals selectItem.ListID
    select selectItem;

var requiredList = query.ToList();

Это работает, проверьте снимок экрана. enter image description here

РЕДАКТИРОВАТЬ

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

var query = from item in itemList
    group item by item.ListID into gr
    where gr.Select(s=>s.ItemId).Distinct().Count() == MaxItemID
    join i in itemList on gr.Key equals i.ListID
    select i;
2 голосов
/ 02 февраля 2012
int distinctIDs = items.Select(x => x.ItemID).Distinct().Count();
var newList = items
    .GroupBy(x => x.ListID)
    .Where( x => x.Select(y=>y.ItemID).Distinct().Count() ==  distinctIDs)
    .SelectMany(x => x.ToList())
    .ToList();
2 голосов
/ 02 февраля 2012

Я надеюсь, что это ваша цель:

var list = 
     ItemList
    .GroupBy(p=>p.ListID)
    .Where(p=>p.Distinct().Count()<MaxItemID)
    .ToArray()
0 голосов
/ 02 февраля 2012

Невозможно прокомментировать производительность версии Linq, но есть решения Linq и non-linq

чч,
Alan

Редактировать

В примере данных показаны дубликаты listId / ItemId, поэтому я пропустил отдельную проверку, но при необходимости он идет как первая часть оператора linq.

Редактировать 2

Обновили код Linq.
Не обновил код non-linq. Просто проверьте, не изменился ли предыдущий код перед тем, как добавить (предполагается, что отсортировано, ListId, ItemId согласно примеру ввода.

[TestMethod]
public void LinqVersion() {

    Dictionary<int, List<ListItem>> found = new Dictionary<int, List<ListItem>>();

    var comparer = new ListItemEqualityComparer();

    var actual = Input.Distinct(comparer).GroupBy(lstItem => lstItem.ListId).Where(grp => grp.Count() == 4).SelectMany(grp => grp);

    Assert.IsTrue(Expected.SequenceEqual(actual, comparer));

}


[TestMethod]
public void NoLinqVersion() {

    Dictionary<int, List<ListItem>> found = new Dictionary<int, List<ListItem>>();

    foreach (var listItem in Input) {
      AddItem(found, listItem.ListId, listItem);
     }

    var actual = new List<ListItem>();
    foreach (var pair in found) {
       if (pair.Value.Count == 4) {
           actual.AddRange(pair.Value);
       }
    }

    Assert.IsTrue(Expected.SequenceEqual(actual, new ListItemEqualityComparer()));

}

    private static void AddItem(IDictionary<int, List<ListItem>> dictionary, int listId, ListItem listItem) {
        if (!dictionary.ContainsKey(listId)) {
            dictionary.Add(listId, new List<ListItem>());
        }
        dictionary[listId].Add(listItem);
    }

    public class ListItem {
        public int ListId { get; set; }
        public int ItemId { get; set; }
    }

    public class ListItemEqualityComparer : IEqualityComparer<ListItem> {
        public bool Equals(ListItem x, ListItem y) {
            return x.ListId == y.ListId && x.ItemId == y.ItemId;
        }

        public int GetHashCode(ListItem obj) {
            return obj.ListId ^ obj.ItemId;
        }
    }

    public List<ListItem> Input = new List<ListItem>(){
        new ListItem{ ListId = 1 , ItemId = 1},
        new ListItem{ ListId = 2 , ItemId = 1},
        new ListItem{ ListId = 2 , ItemId = 2},
        new ListItem{ ListId = 2 , ItemId = 3},
        new ListItem{ ListId = 2 , ItemId = 4},
        new ListItem{ ListId = 3 , ItemId = 1},
        new ListItem{ ListId = 3 , ItemId = 2},
        new ListItem{ ListId = 4 , ItemId = 1},
        new ListItem{ ListId = 4 , ItemId = 2},
        new ListItem{ ListId = 4 , ItemId = 3},
        new ListItem{ ListId = 4 , ItemId = 4},
        new ListItem{ ListId = 5 , ItemId = 1},
        new ListItem{ ListId = 5 , ItemId = 2},
    };


    public List<ListItem> Expected = new List<ListItem>{
        new ListItem{ ListId = 2 , ItemId = 1},
        new ListItem{ ListId = 2 , ItemId = 2},
        new ListItem{ ListId = 2 , ItemId = 3},
        new ListItem{ ListId = 2 , ItemId = 4},
        new ListItem{ ListId = 4 , ItemId = 1},
        new ListItem{ ListId = 4 , ItemId = 2},
        new ListItem{ ListId = 4 , ItemId = 3},
        new ListItem{ ListId = 4 , ItemId = 4}
    };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...