En utilisant les expressions lambda pour obtenir un sous-ensemble où les éléments du tableau sont égaux
J'ai un problème intéressant, et je n'arrive pas à comprendre l'expression lambda pour faire ce travail.
J'ai le code suivant:
List<string[]> list = GetSomeData(); //Returns large number of string[]'s
List<string[]> list2 = GetSomeData2(); //similar data, but smaller subset
List<string[]> newList = list.FindAll(predicate(string[] line){
return (???);
});
Je veux retourner uniquement les enregistrements dans la liste dans laquelle l'élément 0 de chaque string[] est égal à celui de l'élément 0 est dans la liste 2.
liste contient les données comme ceci:
"000", "Data", "more data", "etc..."
liste 2 contient des données comme ceci:
"000", "different data", "even more different data"
Fondamentalement, je pourrais écrire ce code comme ceci:
List<string[]> newList = new List<string[]>();
foreach(var e in list)
{
foreach(var e2 in list2)
{
if (e[0] == e2[0])
newList.Add(e);
}
}
return newList;
Mais, je vais essayer d'utiliser des génériques et lambda est plus, donc, je suis à la recherche d'un bien propre solution. C'est frustrant moi mais.. peut-être Trouver à l'intérieur d'un Trouver?
EDIT:
La réponse de Marc-dessous m'amènent à expérimenter avec une varation qui ressemble à ceci:
var z = list.Where(x => list2.Select(y => y[0]).Contains(x[0])).ToList();
Je ne suis pas sûr de savoir comment efficace c'est, mais il fonctionne et est assez succincte. Quelqu'un d'autre avez des suggestions?
OriginalL'auteur Erik Funkenbusch | 2009-02-15
Vous devez vous connecter pour publier un commentaire.
Vous pouvez vous joindre? Je voudrais utiliser deux étapes de moi-même:
Si vous avez seulement .NET 2.0, puis installer LINQBridge et utiliser le haut (ou similaire avec un
Dictionary<>
si LINQBridge ne comprend pasHashSet<>
), ou peut-être utiliser imbriquéeFind
:noter, cependant, que la
Find
approche est O(n*m), où-comme leHashSet<>
approche est O(n+m)...remarque: pour les très petites listes, être plus efficace, il suffit de scanner la liste [comme votre modification ne]... mais pour les petites listes, il est va être très rapide, peu importe l'approche que vous utilisez. Comme la taille de la liste augmente, l'analyse de l'approche peut rapidement devenir un goulot d'étranglement.
Ok. Un morceau de infromation je me dois de mentionner est que les "clés" (ou liste 2) sera toujours relativement faible, probablement moins de 10. Alors que la source (liste) peut être de plusieurs centaines d'éléments (jusqu'à 1000).
Mais en général: beaucoup plus efficace, oui. Tout d'abord, il ne garde que le distinct clés; d'autre part, il utilise un algorithme de hachage (similaire à un dictionnaire), de sorte que Contient tend à O(1) au lieu de O(n) [essentiellement, le considèrent comme un "index" dans la base de données de termes].
Si vous avez < 10 touches (liste 2), puis une ou l'autre approche doit être fine.
OriginalL'auteur Marc Gravell
Vous pouvez utiliser l'Intersection de la méthode d'extension dans le Système.Linq, mais vous devez fournir une IEqualityComparer pour faire le travail.
Dépend du contexte en fait. Si cela vient à plusieurs reprises, de mettre votre comparateur d'égalité dans une bibliothèque de l'assemblée et vous pouvez utiliser un simple appel à se Croisent pour obtenir l'Intersection de vos deux listes. Plus tard, si vous le souhaitez, vous pouvez utiliser le même programme pour d'égal à Égal, ou, Sauf, ou d'autres utilisations
OriginalL'auteur David Wengier
se Croisent le travail pour vous.Se croisent trouve tous les éléments qui sont dans les deux listes.
Ok re-lecture de la question. Se croisent ne prend pas en compte la commande.
J'ai écrit un peu plus complexe linq expression qui renvoie une liste d'éléments qui sont dans la même position (index) avec la même valeur.
Explication de la requête:
Sélectionner un ensemble de valeurs et la position de cette valeur.
Filtre de définir l'emplacement de l'élément dans la même position dans la deuxième liste a la même valeur.
Sélectionnez simplement la valeur de l'indice).
Noter que j'ai utilisé:
list2.Skip(w.Index).FirstOrDefault()
//instead of
list2[w.Index]
De sorte qu'il sera de gérer des listes de longueurs différentes.
Si vous connaissez les listes sont de la même longueur ou list1 sera toujours plus court que
list2[w.Index]
serait probablement un peu plus vite.OriginalL'auteur DarcyThomas