J'utilise LINQ depuis un certain temps maintenant, mais semble être bloqué sur quelque chose en ce qui concerne les articles uniques, j'ai la liste suivante:
List<Stock> stock = new List<Stock>();
Cela a les propriétés suivantes: ID de chaîne, type de chaîne, description de chaîne, exemple:
public class Stock
{
public string ID { get; set; }
public string Type { get; set; }
public string Description { get; set; }
}
Je souhaite avoir une requête LINQ qui regroupera les articles en stock par leur type et les renverra en tant que nouvelle liste de stock (elle doit être du même type que la liste de stock d'origine).
Exemples de données:
ID Type Description
----------------------------------------------
1 Kitchen Appliance Dishwasher
2 Living Room Television
3 Kitchen Appliance Washing Machine
4 Kitchen Appliance Fridge
...
Ma requête Linq veut pouvoir retourner tous les appareils de cuisine par exemple.
Je transmettrais donc ceci en tant que "type" dans la requête et il retournerait les éléments 1, 3 et 4 de cet exemple de liste.
Cette liste retournée doit également être de type: List<Stock>
.
Essentiellement, je veux une liste des éléments uniques par type, un peu comme une requête SQL Distinct, comment puis-je y parvenir dans LINQ?
Les solutions alternatives sont correctes mais doivent être uniquement du code client Silverlight/C #.
Une autre précision est que je ne peux pas non plus fournir le paramètre "Kitchen Appliance" et que je veux juste les uniques, par exemple. il y a.
Utilisez GroupBy
et ToDictionary
pour créer un dictionnaire de List<Stock>
valeurs saisies sur la propriété Type
:
var appliancesByType = stock
.GroupBy(item => item.Type)
.ToDictionary(grp => grp.Key, grp => grp.ToList());
Ensuite, vous pouvez accéder aux types eux-mêmes ainsi qu'à une liste pour tout type donné assez facilement:
// List of unique type names only
List<string> stockTypes = appliancesByType.Keys.ToList();
// Or: list of one stock item per type
List<Stock> exampleStocks = appliancesByType
.Select(kvp => kvp.Value[0])
.ToList();
// List of stock items for a given type
List<Stock> kitchenAppliances = appliancesByType["Kitchen Appliance"];
Cette approche prend vraiment soin de tous vos besoins, comme je le vois. Mais pour d'autres options, voir ci-dessous.
Vous pouvez toujours simplement utiliser Where
pour obtenir les éléments du type souhaité, puis ToList
pour placer ces éléments dans un nouveau List<Stock>
:
List<Stock> kitchenAppliances = stock
.Where(item => item.Type == "Kitchen Appliance")
.ToList();
En réponse à cette dernière partie:
Une autre précision est que je ne peux pas non plus fournir le paramètre "Kitchen Appliance" et que je veux juste les uniques, par exemple. il y a.
Ici, vous semblez vouloir quelque chose de complètement différent: fondamentalement le comportement fourni par Distinct
. Pour cette fonctionnalité, vous pouvez essentiellement utiliser réponse de Soonts (éventuellement, renvoyer un IEnumerable<tKey>
au lieu de IEnumerable<tSource>
), ou vous pouvez simplement utiliser Distinct
en combinaison avec Select
pour éviter d'avoir à implémenter un IEqualityComparer<Stock>
(voir ci-dessous).
En réponse à votre clarification, voici ma recommandation: deux méthodes, une pour chaque objectif ( principe de responsabilité unique ):
// This will return a list of all Stock objects having the specified Type
static List<Stock> GetItemsForType(string type)
{
return stock
.Where(item => item.Type == type)
.ToList();
}
// This will return a list of the names of all Type values (no duplicates)
static List<string> GetStockTypes()
{
return stock
.Select(item => item.Type)
.Distinct()
.ToList();
}
On dirait que c'est une simple clause Where nécessaire.
List<Stock> kitchen= stock.Where(s=>s.Type=="Kitchen Appliance")
.OrderBy(s=>s.Description).ToList();
Si vous vouliez strictement le Types
contenu dans la liste source:
string[] typesFound = stock.Select(s=>s.Type).Distinct().ToArray();
static class EnumerableEx
{
// Selectively skip some elements from the input sequence based on their key uniqueness.
// If several elements share the same key value, skip all but the 1-st one.
public static IEnumerable<tSource> uniqueBy<tSource, tKey>( this IEnumerable<tSource> src, Func<tSource, tKey> keySelecta )
{
HashSet<tKey> res = new HashSet<tKey>();
foreach( tSource e in src )
{
tKey k = keySelecta( e );
if( res.Contains( k ) )
continue;
res.Add( k );
yield return e;
}
}
}
// Then later in the code
List<Stock> res = src.uniqueBy( elt => elt.Type ).ToList()
var kitchenAppliances = stocks.Where(stock => stock.Type == "Kitchen Appliance");
Vous pouvez également faire quelque chose dans ce sens, dans ce cas, je prends des résultats lucene puis je retire les nœuds parapluies à un type anonyme
var datasource = (from n in SearchResults
select new
{
PageLink = uQuery.GetNode(n.Id).NiceUrl,
uQuery.GetNode(n.Id).Name,
Date = uQuery.GetNode(n.Id).GetProperty("startDate"),
IntroText = string.IsNullOrEmpty(uQuery.GetNode(n.Id).GetProperty("introText").Value) ? string.Empty : uQuery.GetNode(n.Id).GetProperty("introText").Value,
Image = ImageCheck(uQuery.GetNode(n.Id).GetProperty("smallImage").Value)
}).Distinct().ToList();
Je ne comprends probablement pas la question, mais cela me semble être une requête Linq assez simple:
List<Stock> stock = new List<Stock>();
... populate your list as per your example
List<Stock> kitchenAppliances =
(from obj in stock
where obj.Type == "Kitchen Appliance"
select obj).ToList();
ou si vous préférez la syntaxe de la méthode d'extension:
List<Stock> kitchenAppliances =
stock.Where(obj => obj.Type == "Kitchen Appliance").ToList();
Ce que je ne comprends pas, c'est votre utilisation de distinct et unique dans ce contexte. Les objets sont déjà uniques, et il me semble que vous souhaitez une requête basique "donnez-moi tous les appareils de cuisine".