C# create an array from specific values of dictionnary - c#

I've been looking for answers but for some reasons all I found doesn't match with my use.
I'm not very familiar to c#, I have a dictionary
public Dictionary<int, int> deck = new Dictionary<int, int>();
I want to take ten first values of this dictionary and put it in an array like
public string[] cardP1 = new string[10];
, I tried some things with .Take or .CopyTo, I also played with the Values but it is still not working.

you can use LINQ very easily like this :
var q = (from p in deck.Keys select p).Take(10).ToArray();
if you want Values you can just change the deck.keys to deck.values
it will give you the 10 first keys.
EDIT Or as Jakub DÄ…bek commented :
var items = deck.Keys.Take(10).ToArray();

Check this:
if(deck.Count>=10)
{
cardP1 = deck.Take(10).Select(x => x.Value.ToString()).ToArray();
}
Or if you want to have some custom string for example: Card 1: 4
you can go with:
cardP1 = deck.Take(10).Select(x => string.Format("Card {0}: {1}", x.Key, x.Value) ).ToArray();

Related

Sort C# Dictionary by a custom array/list, and output reordered dictionary Values as list

There are a few similar questions, but unfortunately none I've found that offer the answer I require. Help is appreciated.
First Question
I have a dictionary lets say like the below (simplified for example):
IDictionary<string, string> Beatles = new Dictionary<string, string>();
Beatles.Add("Singer", "John");
Beatles.Add("Drummer", "Ringo");
Beatles.Add("Guitar", "Paul");
Beatles.Add("Bass", "George");
Is it possible to reorder the dictionary based on something like a string array or a list below (EDIT - and output a List with just the reordered Values, as someone clarified Dictionaries don't have order):
string[] reorderList = {"Guitar","Bass","Singer","Drummer"};
EDIT - I want the output to be a List containing this order: "Paul", "George", "John", "Ringo"
Secondary Question
Let's say I don't include one of the Dictionary items in my ordering string, like this:
string[] locations = {"Guitar","Singer","Drummer"};
I want all missing items (in this case just "Drums") to be automatically added to the end. Is that possible?
Here's a quick extension that will return what you are asking for:
public static class DictionaryExtension
{
public static List<T> CustomSort<TK, T>(this IDictionary<TK, T> src, TK[] sortList)
{
// items in the sortList
var output = (from key in sortList where src.ContainsKey(key) select src[key]).ToList();
// remaining "other" items
output.AddRange((from item in src where !sortList.Contains(item.Key) select item.Value).OrderBy(o => o));
return output;
}
}
Note: It isn't checking for IComparable so YMMV. And if you have duplicate keys in the reorderList you will get duplicate values in the results.
That's a very interesting problem. First of all as everyone suggested, you cannot reorder Dictionary.
However, you can achieve your desired output by running following piece of code
var pass1 = reorderList.Select(x => Beatles.ContainsKey(x) ? Beatles[x] : null).Where(x => x != null); //Adds desired ordered list of Dictionary values to the list
var result = pass1.Union(Beatles.Values.Except(pass1)).ToList(); //Appends remaining values, if any, to list
Variable result will have your desired output.
Update
Updated above code to take care of invalid values.

How to sort by descending nested Dictionary in C# using LINQ

I need some help to sort by descending nested Dictionary which is quite hard for me because I'm not so advanced , I've been searching many sites but with no success. If someone can give me a hand with this I'll be grateful. So here is the code
Dictionary<string, Dictionary<string, int>> champLeague = new Dictionary<string, Dictionary<string, int>>();
For example when I add -
Barcelona, Arsenal, 1
Man Unted, Liverpool, 2
Man City, Stoke City, 3
And I want to print out the dictionary ordered by descending by the second dictionary's value like this :
var orderedDic = champLeague.OrderByDescending(x => x.Value.Values).ThenBy(x => x.Value.Keys)
And try foreach(var kvp in orderedDic){Console.WriteLine(kvp.Key)}
It throws me an exception : "unhandled exception at least one object must be implemented IComparable"
I want to look like this :
Man City
Man United
Barcelona
foreach (var firstTeam in dictionary)
{
Console.WriteLine($"{firstTeam.Key}");
foreach (var secondTeam in firstTeam.Value.OrderByDescending(x => x.Value))
{
Console.WriteLine($"# {secondTeam .Key} -> {secondTeam .Value}");
}
}
By what I understand, you want to sort the matches in descending order with respect to the number of goals. For this particular problem, I think usage of dictionary is not recommended. You can use tuples instead. They will save you the hassle when a team has more than one matches.
Here is the code.
using System;
using System.Linq;
using System.Collections.Generic;
public class Test
{
public static void Main()
{
var tuple1 =
new Tuple<string, string, int>("Man City", "Stoke City", 3);
var tuple2 =
new Tuple<string, string, int>("Man Unted", "Liverpool", 2);
var tuple3 =
new Tuple<string, string, int>("Barcelona", "Arsenal", 1);
var championsLeague = new List<Tuple<string, string, int>>();
championsLeague.Add(tuple1);
championsLeague.Add(tuple2);
championsLeague.Add(tuple3);
//Item3 is the third item from left that mentioned in the definition of the Tuple. ie. Number of goals.
var lst = championsLeague.OrderByDescending(x => x.Item3)
.Select(x=> x.Item1); // Item1 is the first item mentioned in the tuple definition.
lst.ToList().ForEach(Console.WriteLine);
}
}
You should try
var allMatches = new List<KeyValuePair<KeyValuePair<string, string>, int>>();
foreach(var left in champLeage.Keys)
{
foreach(var right in left){
allMatches.Add(new KeyValuePair(new KeyValuePair<left, right>(left, right.Key), right.Value);
}
}
foreach(var match in allMatches.OrderByDescending(x => x.Value)){
ConsoleWriteLine("{0} - {1} : {2}", match.Key.Key, match.Key.Value, match.Value);
}
This is not efficient or "pretty". You should use classes. A Match class that have 2 teams and a Result or something like that

Suggested structure to maps some strings to some other strings

In my console application I have one hundred county codes and their names. For example:
"01" : "Floyd"
"02" : "Wabash"
When my program uses the values, it reads "01","02"...and I want to get "Floyd", etc...
This list won't grow in future, I am just hard coding them, How do you suggest to access these?
Maybe in a static class? Maybe in a JSON format? Other ways?
Dictionary is what you look for: MSDN link
Short example:
void Main()
{
var dic = new Dictionary<int,string>();
// Instead of having a method to check, we use this Action
Action<int> tryDic = (i) => {
if (dic.ContainsKey(i))
Console.WriteLine("{0}:{1}", i, dic[i]);
else
Console.WriteLine("dic has no key {0}", i);
};
dic.Add(1,"one");
dic.Add(2,"two");
// dic.Keys = 1, 2
// dic.Values = one, two
tryDic(1); // one
tryDic(3); // dic has no key 3 (Happens in Action above)
dic[1]="wow";
tryDic(1); // wow
}
Just use a simple Dictionary<string, string>; if you really want you can wrap it in a class to add some behavior such as handling keys not found, or already existing
You are looking for a Dictionary<string, string>
var values = new Dictionary<string,string>();
values.Add("01", "Floyd");
...
var value = values["01"]; // Floyd

BinarySearch in two dimensional list

I have dimensional list:
List<List<string>> index_en_bg = new List<List<string>>();
index_en_bg.Add(new List<string>() { word1, translation1 });
index_en_bg.Add(new List<string>() { word2, translation2 });
index_en_bg.Add(new List<string>() { word3, translation3 });
I would do binary search by the first column (words), something like this:
int row = index_en_bg.BinarySearch(searchingstr);
but it works only for a one-dimensional list. How would I extend it to work for two-dimensional lists in my case? I don't want to use Dictionary class.
In this case you need to provide your own customer IComparer-implementing comparator
public class Comparer: IComparer<IList<string>>
{
public int Compare(IList<string> x, IList<string> y)
{
// base the comparison result on the first element in the respective lists
// eg basically
return x[0].CompareTo(y[0]);
}
And you'll call it like this, offering a List where only the field you're searching is filled in.
int row = index_en_bg.BinarySearch(new List<string>() {searchingstr},new Comparer());
Well as far as I understand you should use Dictionary<K,V> instead, this way:
// 1 creating the dictionary
var dic = new Dictionary<string, string>();
dic["word1"] = "translation1";
dic["word2"] = "translation2";
dic["word3"] = "translation3";
// 2 finding a translation
var trans = dic["word1"];
And Dictionary<K,V> is really performant.
But if you insist on using BinarySearch you can implement IComparer<List<string>> and pass it to the function.
As you always search using the first item of the list you could use dictionary too.
var d = Dictionary<string, List<string>>();
as answered previously it's preforms much better than List.

C# Convert List<string> to Dictionary<string, string>

This may seem an odd thing to want to do but ignoring that, is there a nice concise way of converting a List<string> to Dictionary<string, string> where each Key Value Pair in the Dictionary is just each string in the List. i.e.
List = string1, string2, string3
Dictionary = string1/string1, string2/string2, string3/string3
I have done plenty of searching and there are literally dozens of examples on Stackoverflow alone of doing it in the opposite direction but not this way round.
The reason for doing this is I have two third part components and changing them is out of my hands. One returns a list of email addresses as a List<string> and the other send emails where the To parameter is a Dictionary<string, string>. The key of the dictionary is the email address and the value is their real name. However, I don't know the real name but it still works if you set the real name to the email address as well. Therefore why I want to convert a List to a Dictionary<string, string>. There are plenty of ways of doing this. A foreach loop on the list which adds a kvp to a dictionary. But I like terse code and wondered if there was a single line solution.
Try this:
var res = list.ToDictionary(x => x, x => x);
The first lambda lets you pick the key, the second one picks the value.
You can play with it and make values differ from the keys, like this:
var res = list.ToDictionary(x => x, x => string.Format("Val: {0}", x));
If your list contains duplicates, add Distinct() like this:
var res = list.Distinct().ToDictionary(x => x, x => x);
EDIT To comment on the valid reason, I think the only reason that could be valid for conversions like this is that at some point the keys and the values in the resultant dictionary are going to diverge. For example, you would do an initial conversion, and then replace some of the values with something else. If the keys and the values are always going to be the same, HashSet<String> would provide a much better fit for your situation:
var res = new HashSet<string>(list);
if (res.Contains("string1")) ...
Use this:
var dict = list.ToDictionary(x => x);
See MSDN for more info.
As Pranay points out in the comments, this will fail if an item exists in the list multiple times.
Depending on your specific requirements, you can either use var dict = list.Distinct().ToDictionary(x => x); to get a dictionary of distinct items or you can use ToLookup instead:
var dict = list.ToLookup(x => x);
This will return an ILookup<string, string> which is essentially the same as IDictionary<string, IEnumerable<string>>, so you will have a list of distinct keys with each string instance under it.
EDIT
another way to deal with duplicate is you can do like this
var dic = slist.Select((element, index)=> new{element,index} )
.ToDictionary(ele=>ele.index.ToString(), ele=>ele.element);
or
easy way to do is
var res = list.ToDictionary(str => str, str=> str);
but make sure that there is no string is repeating...again otherewise above code will not work for you
if there is string is repeating than its better to do like this
Dictionary<string,string> dic= new Dictionary<string,string> ();
foreach(string s in Stringlist)
{
if(!dic.ContainsKey(s))
{
// dic.Add( value to dictionary
}
}
By using ToDictionary:
var dictionary = list.ToDictionary(s => s);
If it is possible that any string could be repeated, either do a Distinct call first on the list (to remove duplicates), or use ToLookup which allows for multiple values per key.
You can use:
var dictionary = myList.ToDictionary(x => x);

Categories

Resources