Создайте список из другого сгруппированного списка. (Оценить по дате)

#c# #.net

#c# #.net

Вопрос:

Я получил список коллекции, которая имеет много атрибутов. В частности, 3 из них: ID1, ID2 (оба идентификатора являются ключами из моей таблицы, ID1 которой в этом случае всегда будет одинаковым), Количество и дата.

Некоторые факты:

  • Я получу список, выбрав все номера ID1.
  • Мне нужно проверить, сколько записей ID2 дублирует мои записи (возможно вернуть более 2 записей) с ID1 и ID2.
  • Если у меня есть более 1 записи с одинаковыми ID1 и ID2, мне нужно будет проверить из тех дублированных записей, в которых есть (если они есть) одинаковое количество. Внутри этих записей мне нужно будет получить самую последнюю (используя переменную DATE) запись, которая повторяется больше раз.

Позвольте мне попробовать это: Пример 1:

  • Запись 1: ID1 = 1, ID2 = 2, Количество = 100, Дата = 09.11.2011
  • Запись 2: ID1 = 1, ID2 = 2, Количество = 100, Дата = 10.11.2011
  • Запись 3: ID1 = 1, ID2 = 2, Количество = 10, Дата = 10.11.2011
  • Запись 4: ID1 = 1, ID2 = 2, Количество = 13, Дата = 10.11.2011

Мне нужно будет добавить элемент (ID1 = 1, ID2 = 2, Количество = 100, Дата = 10.11.2011) в список результатов. Повторяется 2 раза и является более новым, чем запись с датой 11/09/2011

Пример 2:

  • Запись 1: ID1 = 1, ID2 = 2, Количество = 100, Дата = 01.11.2011
  • Запись 2: ID1 = 1, ID2 = 2, Количество = 100, Дата = 02.11.2011
  • Запись 3: ID1 = 1, ID2 = 2, Количество = 120, Дата = 05.11.2011
  • Запись 4: ID1 = 1, ID2 = 2, Количество = 120, Дата = 07.11.2011

Мне нужно будет добавить элемент (запись 4: ID1 = 1, ID2 = 2, Количество = 120, Дата = 07.11.2011). Даже с тем же диапазоном из двух записей с количеством 100 и 120, последняя из них относится к 07.11.2011.

Пример 3:

  • Запись 1: ID1 = 1, ID2 = 2, Количество = 120, Дата = 01.11.2011
  • Запись 2: ID1 = 1, ID2 = 2, Количество = 120, Дата = 02.11.2011
  • Запись 3: ID1 = 1, ID2 = 2, Количество = 120, Дата = 05.11.2011
  • Запись 4: ID1 = 1, ID2 = 2, Количество = 100, Дата = 07.11.2011
  • Запись 5: ID1 = 1, ID2 = 2, Количество = 100, Дата = 08.11.2011

Мне нужно будет добавить элемент (запись 3: ID1 = 1, ID2 = 2, Количество = 120, Дата = 05.11.2011). Даже с записью от 11/08 количество 120 повторяется 3 раза, поэтому я получу самую последнюю запись с этим количеством.

Пример 4:

  • Запись 1: ID1 = 1, ID2 = 2, Количество = 120, Дата = 01.11.2011
  • Запись 2: ID1 = 1, ID2 = 3, Количество = 120, Дата = 02.11.2011
  • Запись 3: ID1 = 1, ID2 = 4, Количество = 120, Дата = 05.11.2011
  • Запись 4: ID1 = 1, ID2 = 5, Количество = 100, Дата = 07.11.2011
  • Запись 5: ID1 = 1, ID2 = 5, Количество = 100, Дата = 08.11.2011

Мне нужно будет добавить запись 1, запись 2, запись 3 и запись 5 (пятая запись дублируется, и мне нужно получить самую последнюю);

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

Я оставлю код, который я пытаюсь разработать, и давайте посмотрим, имеет ли это какой-либо смысл для вас, ребята.

Я получил следующий объект:

 public class MyEntity
{
  pulic int? ID1 {get; set;}
  pulic int? ID2 {get; set;}
  pulic int? Quantity {get; set;}
  public DateTime? Date {get; set;} 
}
  

У моего контроллера есть метод, который использует этот объект в качестве списка и получает из базы данных множество регистров ОС:

 List<MyEntity> list = new List<MyEntity>();

//The Method "getObjects" recieves the parameters ID1, ID2. Since the 2nd parameter is null.
//It will return a list with all the ID2 registers since they have the same ID1 as the one I used.
list.AddRange(getObjects(ID1,null);
  

Я определенно понятия не имею, как выполнить мои требования. Я не знаю, лучше ли сначала разделить записи, в которых есть только одна запись, а затем отфильтровать другие записи или сделать все вместе.

Есть некоторые пользователи, которые собираются проверить некоторое оборудование внутри грузовиков. Каждый парень в каждом грузовике генерирует идентификатор (ID1) с датой этого. Этот идентификатор относится к конференции hole, которую проводит этот конкретный пользователь. Каждое оборудование (ID2, другая таблица) получило эксклюзивный идентификатор со своим конкретным количеством (Quantity). Поскольку это зависит от пользователя, мне нужно учитывать, что на этой конференции может быть какая-либо ошибка. Вот почему мне нужно учитывать количество, которое повторялось большую часть времени. Если у меня есть количество 100 два раза после последнего количества 120, которое повторялось четыре раза, я бы рассмотрел последний регистр из ID1 и ID2, который получил количество 120

Комментарии:

1. Пожалуйста, опубликуйте написанный вами код

2. Я думаю, вам нужно немного прояснить, что вы делаете. Это похоже на проблему ВЫБОРА N 1, но я могу ошибаться, потому что я не знаю, «я получу самую последнюю запись из повторяющихся». означает запрос SELECT, цикл for или запрос Linq, или что-то совершенно другое

3. Можете ли вы добавить исходный код? Без этого мы работаем в темноте, чтобы понять, как мы могли бы помочь вашему коду быть более эффективным.

4. @conraddfrix У меня есть переменная Date (тип DateTime, который невозможно дублировать), из которой я могу получить самую последнюю, поскольку у меня есть все дублированные записи (элементы, которые имеют одинаковые ID1, ID2 и количество)

5. Ребята, я только что добавил кое-какую информацию, не могли бы вы мне помочь? Я все еще пытаюсь разработать это.. Спасибо!

Ответ №1:

Я бы разбил это на 2 более простых шага.

 // for each combination of ID1 and ID2
// return the latest item from the 
// most frequently-occuring quantity
IEnumerable<MyEntity> GetLatestMaxByID(IEnumerable<MyEntity> list) {
    foreach (var group in list.GroupBy(x => new { x.ID1, x.ID2 }))
        yield return GetSingleItemForIDs(group);
}

// return the latest item from the 
// most frequently-occuring quantity
MyEntity GetSingleItemForIDs(IEnumerable<MyEntity> list) {
    return list.GroupBy(x => x.Quantity)
               .MaxBy(g => g.Count())
               .MaxBy(x => x.Date);
}

// use MaxBy from the morelinq (http://code.google.com/p/morelinq) 
// or use a simplified one here
// Get the maximum item based on a key
public static T MaxBy<T, U>(this IEnumerable<T> seq, Func<T, U> f) {
    return seq.Aggregate((a, b) => Comparer<U>.Default.Compare(f(a), f(b)) < 0 ? b : a);
}
  

Комментарии:

1. Это выглядит великолепно! Спасибо за помощь. Позвольте мне спросить: если дата была получена от другого объекта, который содержит ID1. (MyEntity с ID1, ID2 и количеством) и другой объект с (ID1, дата). Код сильно изменится? Еще раз спасибо!

2. @Dan-SP: Я не уверен, как вы можете получить дату из этого формата. Например, если у вас есть (ID1, ID2, Quantity) = [(1,20, 5), (1, 21, 10)] , а у вас есть (ID1, Date) = [(1, '1/1/2011')] , как вы узнаете, к какой записи это 1/1/2011 относится?

3. Это своего рода порядок! Итак, идентификатор заказа равен ID1, DATE = Дата заказа, ID2 = идентификатор каждого продукта заказа.. Таким образом, я могу считать, что ID2 были упорядочены по ПОРЯДКУ X и ДАТЕ Y. Дата будет применена ко всем ID2 ИДЕНТИФИКАТОРА ЗАКАЗА ID1.

4. @Dan-SP: В таком случае это не сильно изменило бы код, но на самом деле было бы проще. В ваших примерах у вас разные даты для каждого заказа, но если вы знаете, что дата для заказа всегда одна и та же, вам даже не нужно проверять это GetSingleItemForIDs и беспокоиться только о количестве.

5. Я только что отредактировал основной пост, потому что мое объяснение получилось довольно длинным. Проверьте это. Последний абзац.