I have a Dictionary<int?,List<string>>. I need to output pairs of keys and values sorted by keys in ascending order. First, I think to use OrderedDictionary but it saves both keys and values in type of object. Maybe somehow it could be done through the extension methods?
You have two options here:
Use a SortedList<TKey,TValue>/SortedDictionary<TKey,TValue>:
var sortedData = new SortedList<int?, List<string>>(currentDictionary);
Use Linq's OrderBy:
var sortedData = currentDictionary.OrderBy(x => x.Key);
You can use any of these options with the following printing:
foreach (var entry in sortedData)
{
Console.WriteLine("Key: {0}, Values: ", entry.Key);
foreach (var value in entry.Value)
{
Console.WriteLine(value);
}
}
Dictionary<int?, List<string>> yourDictionary = GetTheDictionary();
var sortedKeys = yourDictionary.Select(kvp => kvp.Key).OrderBy(k => k);
This will give you a list of all of your keys in ascending order
If you want your dictionary the same. Ie still as Key Value Pairs. Just ordered by the key then you need to do.
yourDictionary.OrderBy(kvp => kvp.Key);
Related
I have a Dictionary, which has a hash table, that is, keys are not sorted.
Conflicts oConflicts = oClash.Conflicts;
Dictionary<string, string> dConflicts = new Dictionary<string, string>();
Conflict oConflict;
for (int iLoopC = 1; iLoopC <= oConflicts.Count; iLoopC++)
{
oConflict = oConflicts.Item(iLoopC);
if (Math.Abs(oConflict.Value) < 3)
{
dConflicts.Add(oConflict.Value.ToString(), oConflict.SecondProduct.ToString());
}
}
I have sorted the dictionary by LINQ:
var sortedDict = dConflicts.OrderBy(x => x.Value).ToDictionary(x => x.Key, x => x.Value);
I am new to this. Could someone help me with how to get the value stored in sortedDict using the particular key value? Like the last value using count the array elements.
This seems that you are only using a Dictionary just to be sure not Adding duplicates, pretty overkill, but hey...
var searchedLastElement = dConflicts.OrderBy(x => x.Value).LastOrDefault().Value;
yod didn't need the sorted list to be cast again to dictionary only to retrieve the last element
very new to c#.
I'm working with an API that returns a dictionary with 2 keys and 1 value.
This is my current code:
var dic = API.getVehicleValidMods((VehicleHash)sender.vehicle.model);
foreach (KeyValuePair<int, Dictionary<int, string>> kvp in dic)
{
Dictionary<int, string> kvp2 = kvp.Value;
foreach (KeyValuePair<int, string> kvp3 in kvp2)
{
API.consoleOutput("Key = {0}, Key = {1}, Value = {2}", kvp.Key, kvp3.Key, kvp3.Value);
Here is a sample from the result it returns:
As you can see the first keys are sometimes the same number and they sometimes skip numbers.
I'm trying to return all matching "key number 2" that matches a certain "key 1".
The string values are not of importance in my case, I'm only interested in the ints.
So, my pseudo logic tells me something like
"foreach keynumber2 in keynumber1 (the integer, eg. 23) do this:"
should work, however I'm unsure how to code it properly.
tl;dr How do i find all "key2" that matches a certain "key1" ?
So, you want to find all inner keys of specific outer key. You can do this with this line of code:
var key1 = 42;
var allKeys = dic.ContainsKey(key1)
? dic[key1].Keys.ToArray()
: new int[0];
If outer dictionary contains 42 as a key this will return all inner keys. Otherwise it will return an empty ints array.
var matchesFrom1 = from val in dic where val.Key == 1 select val.Value;
var valueList = from val in matchesFrom1 where val.Key == 2 select val.Value;
valueList is the string of values returned
You could use LINQ methods:
Use .Where method to filter your initial collection of KeyValuePairs<> by key.
Use SelectMany to flatten resulting IEnumerable<KeyValuePair<int, Dictionary<>>> to a simple IEnumerable<int>
Use Distinct to make sure there are no duplicate keys (or omit this part if it is not necessary).
var someKey = 16;
var result = dic
.Where(x => x.Key == someKey)
.SelectMany(kv => kv.Value.Keys)
.Distinct()
.ToArray();
I have some dictionary. Let it be:
var dictionary = new Dictionary< string, List<MyClass>>();
I need to convert it to list of object that contains property from key and value.
I did it with foreach loop in the next way:
var list = new List<dynamic>();
foreach (var key in dictionary.Keys)
{
var values = dictionary[key];
foreach (var obj in values)
{
list.Add(new
{
obj.Property0,
obj.Property1,
obj.Property2,
...
key
}
);
}
}
It works, but looks rudely as for me. Is it possible to do it more gracefully with LINQ?
You can do that with a SelectMany.
var list = dictionary.SelectMany(
kvp => kvp.Value,
(kvp,obj) => new {obj.Property0, obj.Property1, obj.Property2, kvp.Key})
.ToList();
Or in query snytax
var list = (from kvp in dictionary
from obj in kvp.Value
select new {obj.Property0, obj.Property1, obj.Property2, kvp.Key})
.ToList();
Note this results in a list of an anonymous class. If you really want dynamic you'll need to do a Cast<dynamic>() before the ToList(). Also if you want the last property of the anonymous class to be key instead of Key you'll need to do key = kvp.Key.
I have a list that I want to put in a dictionary, for simplicity the values being inserted will all be the same.
I can use a foreach loop.
List<string> list = new List<string>();
list.Add("Earth");
list.Add("Wind");
list.Add("Fire");
list.Add("Water");
list.Add("Water"); // Will NOT BE INSERTED using the foreach loop
var myDictionary= new Dictionary<string, int>();
foreach (string value in list)
{
if (!myDictionary.ContainsKey(value))
{
myDictionary.Add(value, 1);
}
}
The above works.
But I want to use ToDictionary do the same in the following way -
Dictionary<string, int> myDictionary2 = list.ToDictionary(i => i, i => 1);
Of course this fails because I'm adding "Water" twice.
What is the correct way of checking for duplicate entries when using ToDictionary?
You could use Distinct() to filter out duplicates:
Dictionary<string, int> myDictionary2 = list.Distinct().ToDictionary(i => i, i => 1);
The same approach would make your traditional loop much clearer too, since you don't have to check "manually" for duplicates:
foreach (string value in list.Distinct())
{
myDictionary.Add(value, 1);
}
Distinct is one option that avoids the duplicate key issue. If you need a count of duplicates, you might try something more like this GroupBy as follows:
var dict = list.GroupBy(i => i).ToDictionary(g => g.Key, g => g.Count());
If your application is not just a simple string-list/duplicate-count structure, you might get some mileage from choosing a different structure like a Lookup that you can get from calling the ToLookup extension -or possibly going with a Grouping like the GroupBy I used above.
I have a dictionary that has int keys. The keys are in random order and are not necesserily consequtive (e.g. 5, 3, 11, 12, 10, 4). I would like to visit each key-value pair in reverse order of key size. So for the example above I'd like to visit (12,11,10...).
The way I see how to do this is to get a count of the number of elements, find the max key by say binary search and then find the next largest value that is smaller than the current max etc. untill I've processed the number of elements contained in the dictionary.
However, there could be a method already existing. For a discussion on how to find the max key: Get the largest key in a dictionary
var pairs = dictionary.OrderByDescending(pair => pair.Key);
foreach(var pair in pairs)
{
var value = pair.Value;
...
}
foreach (var p in myDict.OrderByDescending(pair => pair.Key)) {
// process pair
}
Well, it's easy enough to retrieve all of the keys from a dictionary, you can then use the LINQ OrderByDescending() operator to get them in reverse order:
foreach( var key in yourDictionary.Keys.OrderByDescending(x => x) )
{
// your logic here
}
If you need the value associated with the key, you can also do:
foreach( var keyValuePair in yourDictionary.OrderByDescending(kvp => kvp.Key) )
{
// your logic here
}
You can, of course, use query comprehension syntax is LINQ as well:
var yourResult = from kvp in dictionary
order by kvp.Key descending
select YourProjectionFunction(kvp);
dic = dic.OrderByDescending(p=>p.Key).ToDictionary(p => p.Key, p => p.Value);