Eagle32 Ответов: 2

Фильтр словаря, содержащего сложный тип, с помощью LINQ


Привет,

Я работаю с API, который предоставляет мне следующую коллекцию:
Dictionary<string,list<product>>


Ключ - это код продукта, а значение-это список, содержащий фактический объект продукта.

Сущность Product в приложении C# содержит следующие свойства:
код продукта
название продукта
Product_DESC
код изделия
вид продукции


Сущность Product_TYPE в приложении C# является сложным типом и содержит следующие свойства:
Product_TYPE_CODE
Product_TYPE_DESC


Product_Code и Product_Type могут быть null, потому что эти столбцы в базе данных также могут быть установлены в null.

Конечный пользователь в моем приложении предоставляет список Product_codes и / или Product_types. Теперь что касается списка ProductType, то если значение "неизвестно", я хотел бы сопоставить это значение с нулевым значением для этого конкретного свойства и заменить его на"неизвестно".

Итак, скажем, у меня есть список ProductTypes, и этот список содержит значение "UNKNOWN", которое я хочу сопоставить со свойством ProductType сущности C#.

Как я могу сделать это с помощью LINQ?

Я ценю помощь/совет относительно вышеизложенного.

Что я уже пробовал:

Я попробовал следующий код, который приходит из API, но у меня возникли трудности с использованием LINQ для фильтрации продуктов, используя предоставленный список ProductTypes и ProductCodes и заменяя свойство ProductType:

var loadedProducts = ProductFactory.Способность();

Этот метод, по сути, получает продукты из БД и кэширует их соответствующим образом. Возвращаемое значение при вызове этого метода
Dictionary<string,list<product>>()


Подходит ли LINQ для использования в этом контексте или это не очень хорошая идея использовать LINQ?

Я могу отфильтровать продукты по PRODUCT_CODE и PRODUCT_TYPE, выполнив следующие действия в SQL(это все еще находится в стадии разработки, но я хотел продемонстрировать, что я могу сделать до сих пор в SQL).

SELECT PRODUCT_ID,
 PRODUCT_CODE,
COALESCE(PRODUCT_TYPE, 'UNKNOWN') as PRODUCT_TYPE,
PRODUCT_DESC,
FROM PRODUCTS
WHERE PRODUCT_CODE IN ('TYAHAH','ABH989')
AND COALESCE(PRODUCT_TYPE, 'UNKNOWN') IN ('ABC','UNKNOWN');

Midi_Mick

Вы почти наверняка можете делать с linq все, что хотите, - я просто не уверен, чего вы ожидаете в результате. У вас есть свой словарь, который имеет значение, которое представляет собой список продуктов. Учитывая ваши входные данные, вам нужен только один список продуктов, собранных из всех списков, или вам нужен список ключей, с которыми связан список продуктов, соответствующих вашим входным данным, или, может быть, список списков, каждый из которых содержит продукт, соответствующий вашим критериям?
Кроме того, вы говорите, что ключ вашего словаря-это PRODUCT_CODE, а PRODUCT_CODE может быть нулевым. Недопустимо иметь ключ словаря null, поэтому я предполагаю, что вы уже перевели его в "неизвестный", прежде чем создавать словарь.

Eagle32

Извините, я обновил свою фактическую проблему и свой SQL.
Я проверил API, Product_Code на самом деле всегда заполняется в базе данных и будет содержать реальное значение (то есть не "неизвестно"), а Product_Type не всегда заполняется фактическим значением.

Что я хотел бы сделать, так это отфильтровать коллекцию словарей и вернуть только список "продуктов". Я хочу, чтобы отфильтровать с помощью пользовательского списка ProductCodes и список ProductTypes.

Я хочу сопоставить код продукта с помощью списка ProductCodeList, предоставленного конечным пользователем. Этот список никогда не будет содержать "неизвестного".

Теперь что касается пользовательского списка providedlist, называемого Producttypes List, то если значение содержит "UNKNOWN", я хочу сопоставить нулевое значение свойства ProductType продукта, существующего в этом списке "product" в словаре, который я упомянул. Затем я хочу заменить нулевое значение свойства на "UNKNOWN".

BillWoodruff

Путаница: вы говорите о словаре .NET, вы говорите о списках.

Пожалуйста, уточните, какого именно результата вы хотите достичь. Вы спрашиваете о том, как создать запрос к базе данных, который возвращает набор данных "сложных объектов", или вы спрашиваете о том, чтобы взять словарь .NET в качестве своего "источника" и что-то сделать с ним с помощью Linq. Почему вы показали код SQL-запроса ? Откуда берутся "списки"? Вы создали классы, которые описываете ?

Eagle32

Извините, я обновил свою фактическую проблему и свой SQL. Я посмотрел на API, с которым работаю, и код продукта в таблице Products всегда заполнен и, следовательно, никогда не равен нулю.

Однако ProductType может быть null, и данные, с которыми я работаю, имеют несколько записей, в которых ProductType равен NULL. Я хочу сопоставить это значение, и если значение равно NULL, а значение в предоставленном пользователем списке ProductTypes равно "UNKNOWN", я хочу заменить значение ProductType, где значение равно NULL, которое существует в словаре<string, list<product="">"На " UNKNOWN".

Я спрашиваю, как бы я отфильтровал данные, которые я получаю обратно, на основе предоставленных Пользователем входных данных, где структура данных возвращаемого значения имеет следующий формат Dictionary< string, list< product="">>();

2 Ответов

Рейтинг:
4

Midi_Mick

Это делает его намного проще - и есть 2 подхода. Будет только один Where во всем этом. Вы можете либо использовать ключ для проверки PRODUCT_CODE, либо просто обработать значения и проверить наличие там кодов продукта и типа.

Вариант 1:

loadedProducts.Where(kv=>userProductCodes.Contains(kv.Key) && userTypeCodes.Contains(kv.Value.TYPE_CODE ?? "UNKNOWN")

или просто использовать коллекцию значений
loadedProducts.Values.Where(product=>userProductCodes.Contains(product.PRODUCT_CODE) && userTypeCodes.Contains(product=>product.TYPE_CODE ?? "UNKNOWN")


Опять же, вышеописанное возвращает запись, где оба параметра истинны (т. е. И PRODUCT_CODE, и TYPE_CODE встречаются в соответствующих списках). Просто измените && к || если вы хотите получить результаты там, где оба они верны.

На самом деле, этот вопрос был частью вдохновения последней статьи Tip/Trick, которую я написал - прочтите ее, она может помочь вам понять, как достичь такого рода вещей для себя.
Поиск предметов в коллекции, соответствующих одному из них...[^]


Eagle32

В какой момент я взываю .Метод ToList (), поэтому я получаю только список "продукт" в конце.

Midi_Mick

Да-в конце. И то, и другое создает IEnumerable<string>, который может быть преобразован в список, массив или даже несколько других более сложных контейнеров.

Рейтинг:
2

Midi_Mick

// Assuming these are populated (or at very least, Instantiated with no elements)
List<string> userProductCodes;
List<string> userTypeCodes;

Dictionary<string, list<product="">> loadedProducts;

List<string> matchingList = loadedProducts
	.Where(kv=>userProductCodes.Contains(kv.Key)) // Selects only items where the key is in the userProductCodes list
	.Select(kv=>kv.Value) // separates out the value of the Key/Value pairs (i.e. the lists), so we now have a list of lists that have an appropriate PRODUCT_CODE
	.Aggregate(new List<string>(), (newList, oldList)=>{ newList.AddRange(oldList); return newList;}) // Now we have combined all the lists into one single big list
	.Where (product=>userTypeCode.Contains(product.TYPE_CODE ?? "UNKNOWN")) // Match the User Type codes up - replaces null with "UNKNOWN" for the check
	.ToList(); // Converts the result to a list.


Примечание: это результат типа "и", то есть продукты, где код продукта находится в списке пользователей, а код типа-в списке типов пользователей.
Чтобы создать список типов или, удалите строку, которая выбирает код продукта из пар ключ / значение, и расширьте строку Where, которая выбирает код типа, чтобы он имел "|| userProductCode.Содержит (продукт.PRODUCT_CODE) " как его условие.


Eagle32

Спасибо, теперь вместо списка продуктов в словаре, если у меня есть только словарь & lt;string, product=""> Как бы я добился вышеуказанного, то есть фильтрации и преобразования в список?

Midi_Mick

Поместите свой ответ в решение, чтобы его можно было отформатировать...см. ниже (через несколько минут)