How delete items from Dictionary - c#

I have
Dictionary<string, List<string>> Dic = new Dictionary<string, List<string>>();
How delete first 1,2,3 elements From Dic. I dont know how make it with "foreach"
foreach (KeyValuePair<string, List<string>> kvPair in Dic)
{
Console.WriteLine(kvPair.Key);
foreach (string str in kvPair.Value)
{
}
}

You can't get item 1,2,3 from the dictionary, you can only remove on the basis of a key.
Dictionary MSDN
The order in which the items are returned is undefined.
You may use Orderby to sort the dictionary on the basis of a key. But to remove an item from the dictionary you will need the key.
See Dictionary.Remove
EDIT: based on your edited question with "foreach"
You can't modify the dictionary while enumerating on it. If you try removing items from the dictionary in the foreach you will get error:
Collection was modified; enumeration operation may not execute.
You may convert the dictionary to an array and then remove the items from the dictionary (something like below, it may be improved or changed, it is just for an idea):
var dicArrray = Dic.ToArray();
foreach (KeyValuePair<string, List<string>> kvPair in dicArrray)
{
if (kvPair.Key.Equals("1"))
Dic.Remove(kvPair.Key);
}
But remember, the order in which the items will be in array is undefined. You can't be sure about it

as habib says you can not delete item from dictionary based upon index, you can only remove item based upon the key, use Remove() method
read more from here- Remove Item in Dictionary based on Value

first, create a collection of keys you want to remove:
var toDelete = new List<string>();
int count = 3;
foreach(var pair in dictionary) {
toDelete.Add(pair.Key);
count -= 1;
if( count==0 ) break;
}
// then when ready - delete
foreach(string key in toDelete) dictionary.Remove(key);
the reason is not to invalidate dictionary enumerator by removing items while enumerating.
also consider that order in which key pairs appear is not explicitly set in specification, so you may not rely on it - even if it works now it may stop working in a next version of framework. Thus you have also to decide what does "first 3" means before creating a list of elements to delete.

To remove an item in a dictionary, use the Remove() method. For example:
Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>();
dictionary.Add("1", new List<string());
dictionary.Remove("1");
The order dictionary elements are added is not maintained. However, if you want to delete the highest key, for example, do something like:
dictionary.Remove(dictionary.Keys.OrderBy().First());

If dic is a "simple" Dictionary, using LINQ you can create a new dictionary from the original and reassign it to dic, like this:
dic = dic.Skip(3).ToDictionary(kv => kv.Key, kv => kv.Value);
As pointed out by astander in a comment and in Habib's answer, the order of the dictionary items is undefined, so you might want to apply this technique on a SortedDictionary only.
In that case, you would need to create a new SortedDictionary from the LINQ result:
dic = new SortedDictionary<string, List<string>>(
dic.Skip(3).ToDictionary(kv => kv.Key, kv => kv.Value));

Related

How to get Distinct keys of all child dictionary elements of all parent dictionary values

I have a dictionary like this...
Dictionary<string, Dictionary<string, double>>
How to get the list of all Distinct or unique child dictionary keys from all dictionaries of all parent dictionary values (parent dictionary values is nothing but child dictionaries)?
which is the fastest way of doing this in C#?
It's really easy using LINQ:
var result = myDict.Values.SelectMany(x => x.Keys)
.Concat(myDict.Keys)
.Distinct()
.ToList();
but even without LINQ it's super easy when you use HashSet<string>:
var set = new HashSet<string>();
foreach(var outerItem in myDict)
{
set.Add(outerItem.Key);
foreach(var innerKey in item.Value.Keys)
{
set.Add(innerKey);
}
}
HashSet<T> will only keep distinct items, so adding the same string twice won't make any difference.
PS. Next time you should try writing the code first, and ask question when you run into issue you can't overcome by yourself. Stack Overflow is not 'I want code, give me code' kind of site.
Then you need to call SelectMany() on Values property of your dictionary and then use Distinct() to get distinct elements from a sequence by using the default equality comparer.
var res = myDict.Values.SelectMany(x => x.Keys).Distinct().ToList();
This code creates a Dictionary with string keys and double values.
Dictionary<string, double> d = new Dictionary<string, double>()
{
};
// Store keys in a List
List<string> list = new List<string>(d.Keys);
// Loop through list
foreach (string k in list)
{
//From here you can choose distinct key
}
If I'm reading this right:
IEnumerable<string> uniqueChildKeys = dictOfDicts
.SelectMany(d => d.Value.Keys)
.Distinct();

Can Dictionary values be populated through a list without looping?

Can we have something like -
Dictionary<string, string> dict = new Dictionary<string, string>();
List<string> keysList= new List<string>();
List<string>valuesList= new List<string>();
//Assuming both the list have the same number of items
dict.keys = keysList;
dict.values = valuesList;
Mostly, I want to know if there is a way to populate the keys and values by directly assigning them to a list?
Mostly, I want to know if there is a way to populate the keys and values by directly assigning them to a list?
No, but just zip them and then use ToDictionary:
var dict = keysList.Zip(valuesList, (key, value) => Tuple.Create(key, value))
.ToDictionary(pair => pair.Item1, pair => pair.Item2);
A dictionary, internally isn't storing the data as two lists. It's storing the data in a hash table, which means it need to take each key, generate a hash for it, and then place the item at the location that corresponding to that hash. Because of this the only way to add a group of items is just to loop through the group and add each item. You can use the LINQ ToDictionary method, as mentioned in another answer, but internally all it's going to do is loop through each item and add it to the dictionary. This prevents you from seeing the loop, but the loop is still there.

The order of elements in Dictionary

My question is about enumerating Dictionary elements
// Dictionary definition
private Dictionary<string, string> _Dictionary = new Dictionary<string, string>();
// add values using add
_Dictionary.Add("orange", "1");
_Dictionary.Add("apple", "4");
_Dictionary.Add("cucumber", "6");
// add values using []
_Dictionary["banana"] = 7;
_Dictionary["pineapple"] = 7;
// Now lets see how elements are returned by IEnumerator
foreach (KeyValuePair<string, string> kvp in _Dictionary)
{
Trace.Write(String.Format("{0}={1}", kvp.Key, kvp.Value));
}
In what order will be the elements enumerated? Can I force the order to be alphabetical?
The order of elements in a dictionary is non-deterministic. The notion of order simply is not defined for hashtables. So don't rely on enumerating in the same order as elements were added to the dictionary. That's not guaranteed.
Quote from the doc:
For purposes of enumeration, each item in the dictionary is treated as a KeyValuePair<TKey, TValue> structure representing a value and its key. The order in which the items are returned is undefined.
You can always use SortedDictionary for that. Note that the dictionary is ordered by Key, by default, unless a comparer has been specified.
I'm skeptic regarding the use of OrderedDictionary for what you want since documentation says that:
The elements of an OrderedDictionary are not sorted by the key, unlike
the elements of a SortedDictionary class.
If you want the elements ordered, use a SortedDictionary. An ordinary hastable/dictionary is ordered only in some sense of the storage layout.
The items will be returned in the order that they happen to be stored physically in the dictionary, which depends on the hash code and the order the items were added. Thus the order will seem random, and as implementations change, you should never depend on the order staying the same.
You can order the items when enumerating them:
foreach (KeyValuePair<string, string> kvp in _Dictionary.OrderBy(k => k.Value)) {
...
}
In framework 2.0 you would first have to put the items in a list in order to sort them:
List<KeyValuePair<string, string>> items = new List<KeyValuePair<string, string>>(_Dictionary);
items.Sort(delegate(KeyValuePair<string, string> x, KeyValuePair<string, string> y) { return x.Value.CompareTo(y.Value); });
foreach (KeyValuePair<string,string> kvp in items) {
...
}
For an OrderedDictionary:
var _OrderedDictionary = new System.Collections.Specialized.OrderedDictionary();
_OrderedDictionary.Add("testKey1", "testValue1");
_OrderedDictionary.Add("testKey2", "testValue2");
_OrderedDictionary.Add("testKey3", "testValue3");
var k = _OrderedDictionary.Keys.GetEnumerator();
var v = _OrderedDictionary.Values.GetEnumerator();
while (k.MoveNext() && v.MoveNext()) {
var key = k.Current; var value = v.Current;
}
Items are returned in the order that they are added.
Associative arrays (aka, hash tables) are unordered, which means that the elements can be ordered in any way imaginable.
HOWEVER, you could fetch the array keys (only the keys), order that alphabetically (via a sort function) and then work on that.
I cannot give you a C# sample because I don't know the language, but this should be enough for you to go on yourself.

unsort Hashtable

i am writing a program in C#
i have a code like this
Hashtable ht = new Hashtable();
ht.Add("1", "One");
ht.Add("2", "Two");
ht.Add("3", "Three");
ht.Add("4", "Four");
but Compiler sort it
i wanna know how can i prevent sorting hashtable
please help me
A HashTable doesn't do sorting as such. It does rearrange the items based on their hash code, so the original order isn't preserved.
If you want to preserve the original order, or want to specify a sort order, you can't use a HashTable only.
To specify a different sort order, you can use a SortedDictionary<T>. To preserve the original order, you can add the items both to a Dictionary<T> and a List<T>.
What do you mean by the compiler sorting it? There is definitely NO sorting done. How are you looping over the items?
I think that order of items when you loop over the keys isn't guaranteed ->
foreach(object key in hashtable.Keys){
...
}
but from your question I think you'd like to retrieve the items in the exact same order as you have inserted them - maybe the best solution would be to keep parallel List of your keys; and retrieve keys for looping over hashtable from there.
Use a Dictionary<int, string> or Dictionary <string, string> instead.
When doing:
Hashtable ht = new Hashtable();
ht.Add("1", "One");
ht.Add("2", "Two");
ht.Add("3", "Three");
ht.Add("4", "Four");
foreach (var k in ht.Keys)
{
Console.WriteLine(k);
}
I see no sorting of any kind taking place.
Hashtables do not preserve the order of inserted items. They are stored in a data structure that has no concept of a "correct" order. You should assume that items in a hashtable will be stored in a random order.
You should use a List or other structure instead of a Hashtable if the order of the items is important.
Try this:
Hashtable ht = new Hashtable();
ht.Add("1", "One");
ht.Add("2", "Two");
ht.Add("3", "Three");
ht.Add("4", "Four");
foreach (var k in ht.Keys.sort)
{
Console.WriteLine(k);
}
Notice the sort after ht.Keys
To get the Values in your hashtable ordered by key (wich is what it looks like you want) use this:
public List<string> GetOrderedValues(HashTable ht)
{
// Get a sorted list of keys
List<string> keys = new List<string>(ht.Keys.Cast<string>());
keys.Sort();
// Get values sorted by key
List<string> values = new List<string>();
foreach (string key in keys)
values.Add(ht[key]);
// Return Sorted Values
return values;
}
You can also separete the first part and then you can get both a list of sorted keys and a list of sorted values.
Another option is return a List of KeyValuePair wichh will be sorted by entry
Then again, why not just remove all the ashle and replace your hashtable with a List of KeyValuePair in the first place?
I found this blog, http://mctexpert.blogspot.com/2014/12/keeping-hash-table-in-order.html
To be specific, using [Ordered] would help with keeping the original sort:
$Hash = [Ordered]#{"Apple"="Red";
"Orange"="Orange";
"Banana"="Yellow";
"Pear"="Green";
"Blueberry"="Blue";
"Plum"="Purple"}

How do you sort a dictionary by value?

I often have to sort a dictionary (consisting of keys & values) by value. For example, I have a hash of words and respective frequencies that I want to order by frequency.
There is a SortedList which is good for a single value (say frequency), that I want to map back to the word.
SortedDictionary orders by key, not value. Some resort to a custom class, but is there a cleaner way?
Use LINQ:
Dictionary<string, int> myDict = new Dictionary<string, int>();
myDict.Add("one", 1);
myDict.Add("four", 4);
myDict.Add("two", 2);
myDict.Add("three", 3);
var sortedDict = from entry in myDict orderby entry.Value ascending select entry;
This would also allow for great flexibility in that you can select the top 10, 20 10%, etc. Or if you are using your word frequency index for type-ahead, you could also include StartsWith clause as well.
Use:
using System.Linq.Enumerable;
...
List<KeyValuePair<string, string>> myList = aDictionary.ToList();
myList.Sort(
delegate(KeyValuePair<string, string> pair1,
KeyValuePair<string, string> pair2)
{
return pair1.Value.CompareTo(pair2.Value);
}
);
Since you're targeting .NET 2.0 or above, you can simplify this into lambda syntax -- it's equivalent, but shorter. If you're targeting .NET 2.0 you can only use this syntax if you're using the compiler from Visual Studio 2008 (or above).
var myList = aDictionary.ToList();
myList.Sort((pair1,pair2) => pair1.Value.CompareTo(pair2.Value));
You could use:
var ordered = dict.OrderBy(x => x.Value).ToDictionary(x => x.Key, x => x.Value);
You can sort a Dictionary by value and save it back to itself (so that when you foreach over it the values come out in order):
dict = dict.OrderBy(x => x.Value).ToDictionary(x => x.Key, x => x.Value);
Sure, it may not be correct, but it works. Hyrum's Law means that this will very likely continue to work.
Looking around, and using some C# 3.0 features we can do this:
foreach (KeyValuePair<string,int> item in keywordCounts.OrderBy(key=> key.Value))
{
// do something with item.Key and item.Value
}
This is the cleanest way I've seen and is similar to the Ruby way of handling hashes.
On a high level, you have no other choice than to walk through the whole Dictionary and look at each value.
Maybe this helps:
http://bytes.com/forum/thread563638.html
Copy/Pasting from John Timney:
Dictionary<string, string> s = new Dictionary<string, string>();
s.Add("1", "a Item");
s.Add("2", "c Item");
s.Add("3", "b Item");
List<KeyValuePair<string, string>> myList = new List<KeyValuePair<string, string>>(s);
myList.Sort(
delegate(KeyValuePair<string, string> firstPair,
KeyValuePair<string, string> nextPair)
{
return firstPair.Value.CompareTo(nextPair.Value);
}
);
You'd never be able to sort a dictionary anyway. They are not actually ordered. The guarantees for a dictionary are that the key and value collections are iterable, and values can be retrieved by index or key, but there is no guarantee of any particular order. Hence you would need to get the name value pair into a list.
You do not sort entries in the Dictionary. Dictionary class in .NET is implemented as a hashtable - this data structure is not sortable by definition.
If you need to be able to iterate over your collection (by key) - you need to use SortedDictionary, which is implemented as a Binary Search Tree.
In your case, however the source structure is irrelevant, because it is sorted by a different field. You would still need to sort it by frequency and put it in a new collection sorted by the relevant field (frequency). So in this collection the frequencies are keys and words are values. Since many words can have the same frequency (and you are going to use it as a key) you cannot use neither Dictionary nor SortedDictionary (they require unique keys). This leaves you with a SortedList.
I don't understand why you insist on maintaining a link to the original item in your main/first dictionary.
If the objects in your collection had a more complex structure (more fields) and you needed to be able to efficiently access/sort them using several different fields as keys - You would probably need a custom data structure that would consist of the main storage that supports O(1) insertion and removal (LinkedList) and several indexing structures - Dictionaries/SortedDictionaries/SortedLists. These indexes would use one of the fields from your complex class as a key and a pointer/reference to the LinkedListNode in the LinkedList as a value.
You would need to coordinate insertions and removals to keep your indexes in sync with the main collection (LinkedList) and removals would be pretty expensive I'd think.
This is similar to how database indexes work - they are fantastic for lookups but they become a burden when you need to perform many insetions and deletions.
All of the above is only justified if you are going to do some look-up heavy processing. If you only need to output them once sorted by frequency then you could just produce a list of (anonymous) tuples:
var dict = new SortedDictionary<string, int>();
// ToDo: populate dict
var output = dict.OrderBy(e => e.Value).Select(e => new {frequency = e.Value, word = e.Key}).ToList();
foreach (var entry in output)
{
Console.WriteLine("frequency:{0}, word: {1}",entry.frequency,entry.word);
}
You could use:
Dictionary<string, string> dic= new Dictionary<string, string>();
var ordered = dic.OrderBy(x => x.Value);
return ordered.ToDictionary(t => t.Key, t => t.Value);
Or for fun you could use some LINQ extension goodness:
var dictionary = new Dictionary<string, int> { { "c", 3 }, { "a", 1 }, { "b", 2 } };
dictionary.OrderBy(x => x.Value)
.ForEach(x => Console.WriteLine("{0}={1}", x.Key,x.Value));
Sorting a SortedDictionary list to bind into a ListView control using VB.NET:
Dim MyDictionary As SortedDictionary(Of String, MyDictionaryEntry)
MyDictionaryListView.ItemsSource = MyDictionary.Values.OrderByDescending(Function(entry) entry.MyValue)
Public Class MyDictionaryEntry ' Need Property for GridViewColumn DisplayMemberBinding
Public Property MyString As String
Public Property MyValue As Integer
End Class
XAML:
<ListView Name="MyDictionaryListView">
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding Path=MyString}" Header="MyStringColumnName"></GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding Path=MyValue}" Header="MyValueColumnName"></GridViewColumn>
</GridView>
</ListView.View>
</ListView>
The other answers are good, if all you want is to have a "temporary" list sorted by Value. However, if you want to have a dictionary sorted by Key that automatically synchronizes with another dictionary that is sorted by Value, you could use the Bijection<K1, K2> class.
Bijection<K1, K2> allows you to initialize the collection with two existing dictionaries, so if you want one of them to be unsorted, and you want the other one to be sorted, you could create your bijection with code like
var dict = new Bijection<Key, Value>(new Dictionary<Key,Value>(),
new SortedDictionary<Value,Key>());
You can use dict like any normal dictionary (it implements IDictionary<K, V>), and then call dict.Inverse to get the "inverse" dictionary which is sorted by Value.
Bijection<K1, K2> is part of Loyc.Collections.dll, but if you want, you could simply copy the source code into your own project.
Note: In case there are multiple keys with the same value, you can't use Bijection, but you could manually synchronize between an ordinary Dictionary<Key,Value> and a BMultiMap<Value,Key>.
Actually in C#, dictionaries don't have sort() methods.
As you are more interested in sort by values,
you can't get values until you provide them key.
In short, you need to iterate through them using LINQ's OrderBy(),
var items = new Dictionary<string, int>();
items.Add("cat", 0);
items.Add("dog", 20);
items.Add("bear", 100);
items.Add("lion", 50);
// Call OrderBy() method here on each item and provide them the IDs.
foreach (var item in items.OrderBy(k => k.Key))
{
Console.WriteLine(item);// items are in sorted order
}
You can do one trick:
var sortedDictByOrder = items.OrderBy(v => v.Value);
or:
var sortedKeys = from pair in dictName
orderby pair.Value ascending
select pair;
It also depends on what kind of values you are storing: single (like string, int) or multiple (like List, Array, user defined class).
If it's single you can make list of it and then apply sort.
If it's user defined class, then that class must implement IComparable, ClassName: IComparable<ClassName> and override compareTo(ClassName c) as they are more faster and more object oriented than LINQ.
Required namespace : using System.Linq;
Dictionary<string, int> counts = new Dictionary<string, int>();
counts.Add("one", 1);
counts.Add("four", 4);
counts.Add("two", 2);
counts.Add("three", 3);
Order by desc :
foreach (KeyValuePair<string, int> kvp in counts.OrderByDescending(key => key.Value))
{
// some processing logic for each item if you want.
}
Order by Asc :
foreach (KeyValuePair<string, int> kvp in counts.OrderBy(key => key.Value))
{
// some processing logic for each item if you want.
}
Suppose we have a dictionary as:
Dictionary<int, int> dict = new Dictionary<int, int>();
dict.Add(21,1041);
dict.Add(213, 1021);
dict.Add(45, 1081);
dict.Add(54, 1091);
dict.Add(3425, 1061);
dict.Add(768, 1011);
You can use temporary dictionary to store values as:
Dictionary<int, int> dctTemp = new Dictionary<int, int>();
foreach (KeyValuePair<int, int> pair in dict.OrderBy(key => key.Value))
{
dctTemp.Add(pair.Key, pair.Value);
}
The easiest way to get a sorted Dictionary is to use the built in SortedDictionary class:
//Sorts sections according to the key value stored on "sections" unsorted dictionary, which is passed as a constructor argument
System.Collections.Generic.SortedDictionary<int, string> sortedSections = null;
if (sections != null)
{
sortedSections = new SortedDictionary<int, string>(sections);
}
sortedSections will contain the sorted version of sections
Sort and print:
var items = from pair in players_Dic
orderby pair.Value descending
select pair;
// Display results.
foreach (KeyValuePair<string, int> pair in items)
{
Debug.Log(pair.Key + " - " + pair.Value);
}
Change descending to acending to change sort order
A dictionary by definition is an unordered associative structure that contains only values and keys in a hashable way. In other words has not a previsible way to orderer a dictionary.
For reference read this article from python language.
Link
python data structures
Best way:
var list = dict.Values.OrderByDescending(x => x).ToList();
var sortedData = dict.OrderBy(x => list.IndexOf(x.Value));
The following code snippet sorts a Dictionary by values.
The code first creates a dictionary and then uses OrderBy method to sort the items.
public void SortDictionary()
{
// Create a dictionary with string key and Int16 value pair
Dictionary<string, Int16> AuthorList = new Dictionary<string, Int16>();
AuthorList.Add("Mahesh Chand", 35);
AuthorList.Add("Mike Gold", 25);
AuthorList.Add("Praveen Kumar", 29);
AuthorList.Add("Raj Beniwal", 21);
AuthorList.Add("Dinesh Beniwal", 84);
// Sorted by Value
Console.WriteLine("Sorted by Value");
Console.WriteLine("=============");
foreach (KeyValuePair<string, Int16> author in AuthorList.OrderBy(key => key.Value))
{
Console.WriteLine("Key: {0}, Value: {1}", author.Key, author.Value);
}
}
You can sort the Dictionary by value and get the result in dictionary using the code below:
Dictionary <<string, string>> ShareUserNewCopy =
ShareUserCopy.OrderBy(x => x.Value).ToDictionary(pair => pair.Key,
pair => pair.Value);
Given you have a dictionary you can sort them directly on values using below one liner:
var x = (from c in dict orderby c.Value.Order ascending select c).ToDictionary(c => c.Key, c=>c.Value);

Categories

Resources