web-dev-qa-db-fra.com

Obtenir les clés et les valeurs de C # de la liste <KeyValuePair <chaîne, chaîne>

Étant donné une liste: 

    private List<KeyValuePair<string, string>> KV_List = new List<KeyValuePair<string, string>>();
    void initList()
    {
        KV_List.Add(new KeyValuePair<string, string>("qwer", "asdf"));
        KV_List.Add(new KeyValuePair<string, string>("qwer", "ghjk"));
        KV_List.Add(new KeyValuePair<string, string>("zxcv", "asdf"));
        KV_List.Add(new KeyValuePair<string, string>("hjkl", "uiop"));
    }

(REMARQUE: il existe plusieurs valeurs pour la clé "qwer" et plusieurs clés pour la valeur "asdf".)

1) Existe-t-il un meilleur moyen de renvoyer une liste de toutes les clés que de simplement effectuer un foreach sur la liste KeyValuePair?

2) De même, existe-t-il un meilleur moyen de retourner une liste de toutes les valeurs pour une clé donnée que d'utiliser un foreach?

3) Et ensuite, pourquoi ne pas renvoyer une liste de clés pour une valeur donnée?

Merci...

12
frog_jr
// #1: get all keys (remove Distinct() if you don't want it)
List<string> allKeys = (from kvp in KV_List select kvp.Key).Distinct().ToList();
// allKeys = { "qwer", "zxcv", "hjkl" }

// #2: get values for a key
string key = "qwer";
List<string> values = (from kvp in KV_List where kvp.Key == key select kvp.Value).ToList();
// values = { "asdf", "ghjk" }

// #3: get keys for a value
string value = "asdf";
List<string> keys = (from kvp in KV_List where kvp.Value == value select kvp.Key).ToList();
// keys = { "qwer", "zxcv" }
18
Jashaszun

Il semble que vous utiliseriez quelque chose comme:

Dictionary<string, List<string>> kvlist;

kvlist["qwer"] = new List<string>();
kvlist["qwer"].Add("value1");
kvlist["qwer"].Add("value2");

foreach(var value in kvlist["qwer"]) {
    // do something
}

Il serait relativement facile de créer une classe de dictionnaire de base à valeurs multiples utilisant un dictionnaire et une liste.

Ce article de blog en dit plus sur le type MultiDictionary de Microsoft disponible via NuGet.

5
Robert Horvick

Vous pouvez utiliser NameValueCollection à partir de l'espace de noms System.Collection.Specialized:

NameValueCollection  KV_List = new NameValueCollection();

KV_List.Add("qwer", "asdf");
KV_List.Add("qwer", "ghjk");
KV_List.Add("zxcv", "asdf");
KV_List.Add("hjkl", "uiop");

Exemple d'utilisation:

string singleValue = KV_List["zxcv"];  // returns "asdf"
string[] values = KV_List.GetValues("qwer");  // returns "asdf, "ghjk"
string[] allKeys = KV_List.AllKeys;
string[] allValues = KV_List.AllKeys;

https://msdn.Microsoft.com/en-us/library/system.collections.specialized.namevaluecollection%28v=vs.110%29.aspx

2
Fabjan

Eh bien, vous pouvez utiliser votre LINQ. Mais ce n'est pas "meilleur" (en terme de performance) puisque la boucle est déjà rapide. Il est peut-être plus lisible (préférence personnelle). Pour toutes les réponses ci-dessous, sachez que vous devez importer l’espace de nom System.Linq. Ils renvoient également IEnumerable<T> qui sont chargés paresseux (exécutés lors de leur itération). Si vous souhaitez renvoyer une liste concrète, vous pouvez appeler l'extension .ToList() .

Existe-t-il un meilleur moyen de renvoyer une liste de toutes les clés que de simplement effectuer un foreach sur la liste KeyValuePair?

KV_List.Select(kvp => kvp.Key);

De même, existe-t-il un meilleur moyen de renvoyer une liste de toutes les valeurs d'une clé donnée que d'utiliser un foreach?

var theKeyToLookFor = "qwer";
KV_List.Where(kvp => kvp.Key == theKeyToLookFor).Select(kvp => kvp.Value);

Et ensuite, que diriez-vous de retourner une liste de clés pour une valeur donnée?

var theValueToLookFor = "asdf";
KV_List.Where(kvp => kvp.Value == theValueToLookFor)
       .Select(kvp => kvp.Value)
       .ToList();

Pour plus d'informations sur LINQ, consultez LINQ (Interrogation intégrée au langage)

2
Simon Belanger

J'utiliserais ILookup<K,V> dans votre cas. C'est comme un dictionnaire mais vous pouvez obtenir les valeurs sous la forme IEnumerable<V> avec la même clé.

ILookup<string, string> lookup = KV_List.ToLookup(x => x.Key, x => x.Value);
IEnumerable<string> list = lookup["qwer"];
foreach(string str in list)
{
    Console.WriteLine(str);
}

ou simplement

Console.WriteLine(string.Join(",", lookup["qwer"]));
1
EZI

1:

KV_List.Select(i => i.Key).ToList()

2:

KV_List.Where(i => i.Key == filterByKey).Select(i => i.Value).ToList()

3:

 KV_List.Where(i => i.Value == filterByValue).Select(i => i.Key).ToList()
0
serhiyb

Est-ce que vous lisez ceci et vous vous demandez pourquoi quelqu'un a créé du code avec un IEnumerable <KeyValuePair <A, B >> au lieu d'un Dictionnaire <A, B>, mais vous ne voulez pas demander et souhaitez simplement vous en charger?

if (collection == null)
    return null;

return collection 
    .Where(z => z.Key == aThing)
    .Select(z => z.Value)
    .FirstOrDefault();
0
Stachu