Inline Declaration Of Dictionary<> in C# with FOREACH() - c#

Can anybody help out with the syntax of something like this:
Dictionary<string,string> dict = new Dictionary<string,string>()
{
foreach(var i in collection<Items>)
-----add i to dictionary
}

It's not really clear to me what you mean, but the ToDictionary LINQ extension method may help you. For example:
var dictionary = collection.ToDictionary(item => item.Key,
item => item.Value);
(Obviously you can vary how the key and value are obtained from the item.)

You can use LINQ for this:
Dictionary<string,string> dict = collection.ToDictionary(i => i.MyKey, i => i);

You can do something like UserCollection.ForEach(d => ...add each d.key and d.value to the dictionay and any other logic associated with selecting the key and value), assuming the collection of User types is in a List format or if it's an IEnumerable you can just do .ToList().ForEach(...

Related

LINQ KeyValuePair List select value

I am sure it has been answered somewhere before but for the love of god I cant find it.
I want to get a specific Value for a Key from a KeyValuePair List per LINQ one-liner.
My List: List<KeyValuePair<int, int>> LeagueKVPList
I think it goes something like this:
int x = LeagueKVPList.Where(v => v.Key.(int y)).Value
But that obviously does not work.
Thanks for any help.
You should use Select for that
var values = LeagueKVPList.Select(kvp => kvp.Value);
It returns you all values.
To get a single value you can use FirstOrDefault
var x = LeagueKVPList.FirstOrDefault(kvp => kvp.Key == y).Value;

List of Dictionary to List of another Dictionary

I have a huge list of Dictionary like
List<Dictionary<String,SomeType>> Dict = new List<Dictionary<string,SomeType>>();
I need to convert to the list of dictionary of some other type like below:
List<Dictionary<String,SomeOtherType>> AnotherDict;
Is there a better approach than foreach on the 'Dict' List.
Yes, you can use LINQ:
AnotherDict = Dict.Select(d => d.ToDictionary(pair => pair.Key,
pair => Convert(pair.Value)))
.ToList();
Where Convert is whatever conversion you want to apply to SomeType to construct a SomeOtherType.
EDIT: As noted in comments, this is no more efficient than using nested foreach loops yourselves. It's just simpler.

Making a list distinct in C#

In C#, I have an object type 'A' that contains a list of key value pairs.
The key value pairs is a category string and a value string.
To instantiate object type A, I would have to do the following:
List<KeyValuePair> keyValuePairs = new List<KeyValuePair>();
keyValuePairs.Add(new KeyValuePair<"Country", "U.S.A">());
keyValuePairs.Add(new KeyValuePair<"Name", "Mo">());
keyValuePairs.Add(new KeyValuePair<"Age", "33">());
A a = new A(keyValuePairs);
Eventually, I will have a List of A object types and I want to manipulate the list so that i only get unique values and I base it only on the country name. Therefore, I want the list to be reduced to only have ONE "Country", "U.S.A", even if it appears more than once.
I was looking into the linq Distinct, but it does not do what I want because it I can't define any parameters and because it doesn't seem to be able to catch two equivalent objects of type A. I know that I can override the "Equals" method, but it still doesn't solve the my problem, which is to render the list distinct based on ONE of the key value pairs.
To expand upon Karl Anderson's suggestion of using morelinq, if you're unable to (or don't want to) link to another dll for your project, I implemented this myself awhile ago:
public static IEnumerable<T> DistinctBy<T, U>(this IEnumerable<T> source, Func<T, U>selector)
{
var contained = new Dictionary<U, bool>();
foreach (var elem in source)
{
U selected = selector(elem);
bool has;
if (!contained.TryGetValue(selected, out has))
{
contained[selected] = true;
yield return elem;
}
}
}
Used as follows:
collection.DistinctBy(elem => elem.Property);
In versions of .NET that support it, you can use a HashSet<T> instead of a Dictionary<T, Bool>, since we don't really care what the value is so much as that it has already been hashed.
Check out the DistinctBy syntax in the morelinq project.
A a = new A(keyValuePairs);
a = a.DistinctBy(k => new { k.Key, k.Value }).ToList();
You need to select the distinct property first:
Because it's a list inside a list, you can use the SelectMany. The SelectMany will concat the results of subselections.
List<A> listOfA = new List<A>();
listOfA.SelectMany(a => a.KeyValuePairs
.Where(keyValue => keyValue.Key == "Country")
.Select(keyValue => keyValue.Value))
.Distinct();
This should be it. It will select all values where the key is "Country" and concat the lists. Final it will distinct the country's. Given that the property KeyValuePairs of the class A is at least a IEnumerable< KeyValuePair< string, string>>
var result = keyValuePairs.GroupBy(x => x.Key)
.SelectMany(g => g.Key == "Country" ? g.Distinct() : g);
You can use the groupby statement. From here you can do all kind off cool stuf
listOfA.GroupBy(i=>i.Value)
You can groupby the value and then sum all the keys or something other usefull

c# ToDictionary with ContainsKey check

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.

C# remove duplicate dictionary items from List<>?

So I a collection of dictionary items in a list:
List<Dictionary<string, string>> inputData = new List<Dictionary<string, string>>(inputs);
List<Dictionary<string, string>> itemStack = new List<Dictionary<string, string>>();
Now what I want to do is for each inputData dictionary item I want to check if itemStack has the same value (Dictionary Item) already.
I was thinking it would be like?
foreach (var item in inputData)
{
if(!itemStack.Contains(item){ itemStack.Add(item)}
else{ //Duplicate found}
}
It doesn't really check the items values inside? It just assumes that it doesn't have it...
All i want is if itemStack contains and item that is already in the stack don't include it.
I know I'm missing something obvious.
Thanks,
Dictionary is reference type, so it doesn't check the "deep" value like you expected.
You will have to write your own "Contains" method, either as totally separate method or extension of the Dictionary itself then use it instead, for example:
if(!MyContains(itemStack, item)){ itemStack.Add(item)}
True that a HashSet would be better, but if you want to do it here, try this (assuming you are filtering duplicate keys only):
foreach (var item in inputData.Keys)
{
if (itemStack.Where(x => x.Key == item.Key).Count() > 0)
// There was a duplicate
}
Or, if you only care when the data is coming out you can call:
itemStack.Distinct()
I think, your way is right. On my mind, HashSet is good, but when you add a new element, it performs the same test on the contents of the same items.
Regards.
Based on your initial problem statement, you might do something like this:
var aggregateKnownKeys = itemStack.SelectMany(d => d.Keys);
itemStack.AddRange(
inputData.Select(d=> d.Where(p => !aggregateKnownKeys.Contains(p.Key))
.ToDictionary(p => p.Key, p => p.Value)));
If you only need to combine two dictionaries then you could do this to skip keys that exist in itemStack:
var inputData = new Dictionary<string, string>();
var itemStack = new Dictionary<string, string>();
var oldStack = itemStack;
itemStack = new[] { inputData.SkipWhile(d => oldStack.Keys.Contains(d.Key)), itemStack }
.SelectMany(d => d)
.ToDictionary(d => d.Key, d => d.Value);
Okay so this isn't quite a full answer but it's what I did.
So I have a List of items and instead of doing a full compare to whats in an List(Hence the other considered) I just did a single item check:
if(!String.IsNullOrEmpty(item["itemId"]))
{
alert.DaleksApproaching(item["itemId"]);
}
So when it does see it has a value it just does another event to get rid of it.
The idea of using LINQ and the method approaches about(Contains and Distinct)I like. I have yet to try that, but I plan on doing that. For this it doesn't use LINQ :(
Thanks everyone!

Categories

Resources