C# - sorting Dictionary - c#

I have a Dictionary and I want to sort it by Person, could anyone write me how to do it? Yeah, I tried to find it in the internet, but without success :((
Class subject has 3 parametres - name (string), family_name (string), age (int).
And I want to sort it by for example family_name, if same then by age and finally by name (if also age is same) - could anyone write me the code how to do it?? Thanks a lot for your help ;-)

There are SortedDictionary and SortedList you can use; you'd want to make an IComparer for Person as well. See this for a discussion of their differences: http://msdn.microsoft.com/en-us/library/5z658b67(VS.80).aspx

The Dictionary class can't be sorted due to the way it stores values, but you can easily get a sorted collection of the values that you have in your dictionary using LINQ.
var sorted = dictionary.Values.OrderBy(s => s.name)
.ThenBy(s => s.family_name)
.ThenBy(s => s.age);

Dictionary is structure without order, so you cannot sort it - you can sort ordered structures like list

You can use SortedList or SortedDictionary, both of which sort by the key.
Since the key is a class you created, you can pass an IEqualityComparer into the constructor to control how it gets sorted.

Define a Person and a Comparer class :
public class Person
{
public string Name { get; set; }
public string FamilyName { get; set; }
public int Age { get; set; }
}
public class PersonComparer : IComparer<KeyValuePair<string, Person>>
{
public int Compare(KeyValuePair<string, Person> x, KeyValuePair<string, Person> y)
{
var result = x.Value.FamilyName.CompareTo(y.Value.FamilyName);
if(result != 0)
return result;
return x.Value.Age.CompareTo(y.Value.Age);
}
}
and use these classes lie this :
var myDictionary = new Dictionary<string, Person>();
//fill your dictionary
var list = myDictionary.ToList();
list.Sort(new PersonComparer());
this is a simple and working solution.

Related

Iterate over list inside a dictionary but 1 item from every list at a time

I have a dictionary Dictionary<string, List<string>> MatrixColumns whose content looks like this:
Now, I want to iterate over MatrixColumns Dictionary in such a way that I first get "condition#1" of [0] of key "OPERATOR_ID" and then "delta#1" of [0] of key "DELTA_ID"
and then again "condition#1" of 1 of key "OPERATOR_ID" and then "delta#1" of 1 of key "DELTA_ID" and so on.
Thing to keep in mind is the count of elements inside MatrixColumns can vary and it's not always 2. pls. guide me, How Can I achieve this?
Create a class:
public class MatrixColumnDto
{
public string ColumnName { get; set; }
public List<string> ColumnValues { get; set; }
}
Use LINQ as:
var MatrixColumnsResult = Enumerable.Range(0, MatrixColumns.Max(list
=> list.ColumnValues.Count))
.Select(i => MatrixColumns.Select(list => list.ColumnValues.ElementAtOrDefault(i)).ToList())
.ToList();

Converting a distinct list to dictionary not working

I'm trying to convert a list of objects to a dictionary using the following code:
var MyDictionary = MyList.Distinct().ToDictionary(i => i.ObjectId, i => i);
I know that a dictionary should not contain duplicate elements, hence the .Distinct(). Yet I still get the following Exception whenever there's a duplicate element:
An item with the same key has already been added.
MyList is a list of MyObject that looks like this:
public class MyObject{
public string ObjectId { get; set; }
public string FName { get; set; }
public string LName { get; set; }
}
Is there a better way to create a dictionary from a list of objects ? or am I doing something wrong?
If you want to compare on the ObjectId, you'll need to pass in a custom comparer to .Distinct(). You can do so like this:
class MyObjectComparer : IEqualityComparer<MyObject>
{
public bool Equals(MyObject x, MyObject y)
{
return x.ObjectId == y.ObjectId;
}
public int GetHashCode(MyObject obj)
{
return obj.ObjectId.GetHashCode();
}
}
var MyDictionary = MyList
.Distinct(new MyObjectComparer())
.ToDictionary(i => i.ObjectId, i => i);
You could use Group by and then select first from the List as below:
var MyDictionary = MyList.GroupBy(i => i.ObjectId, i => i).ToDictionary(i => i.Key, i => i.First());
Distinct works using the objects built in Equals and GetHashCode methods by default but your dictionary works only over the id. You need to pass in a IEqualityComparer in to distinct that does the comparison on Id to test if items are equal or make MyObject implment Equals and GetHashCode and have that compare on the Id.

Grab last 5 items of a Collection/List/Dictionary in C#?

I have a class:
public class MatchItem
{
public string round { get; set; }
public string player1 { get; set; }
public string player2 { get; set; }
public string scores { get; set; }
}
Originally I was using a Dictionary:
private Dictionary<string, MatchItem> results = new Dictionary<string, MatchItem>();
A dictionary allows me to access the MatchItem values using a hashed string as the index key.
However, now I have a new need. I would like to be able to access the last X number of items added to the dictionary. What would be the best way to do this?
You can get the last X items using Skip method but you should keep in mind that Dictionary does not have an order, so this might not work as expected, but it will work for ordered collections such as List<T>:
var items = results.Skip(results.Count - 5).Select(x => x.Value);
If you definitely have to keep your values in a dictionary then you will need a helper collection that keeps order of entries or time of entry. In my example I packed it in a very simple wrapper class OrderedDictionary but it doesn't mean you have to have a wrapper class. Easily you can add the helper collection that keeps time of entry to the class where you have your dictionary.
When adding an entry to the dictionary you will have to update the helper dictionary. Here I went for DateTime.Now.Ticks to keep order of entries. Then, when returning items I sort the collection in descending entry time, get requested amount of keys, search these keys in the main dictionary and return the result.
public class OrderedDictionary<T, K>
{
private Dictionary<T, K> baseDictionary;
private Dictionary<long, T> entryTimeDictionary;
public OrderedDictionary()
{
this.baseDictionary = new Dictionary<T, K>();
}
public void Add(T key, K val)
{
this.baseDictionary[key] = val;
this.entryTimeDictionary[DateTime.Now.Ticks] = key;
}
public List<KeyValuePair<T, K>> GetLastEnteredItems(int numberOfEntries)
{
// Find n last keys.
var lastEntries =
this.entryTimeDictionary
.OrderByDescending(i => i.Key)
.Take(numberOfEntries)
.Select(i => i.Value);
// Return KeyValuePair for itmes with last n keys
return this.baseDictionary
.Where(i => lastEntries.Contains(i.Key))
.ToList();
}
}
As said before, you can use the same mechanism in your class. If you however decide to create your own wrapper class it should probably implement IDictionary, ICollection, and IEnumerable interfaces.

Sort ArrayList with custom comparison

I am trying to sort an ArrayList using c#. When the ArrayList contains comparable objects, it is possible to sort with using list.Sort() but I need to sort an ArrayList which contains non-comparable objects. For example, let's say the object is Ring and it has an attribute property Price. Then I need to sort the ArrayList to the price order. If is is possible to select ascending or descending that will more helpful. Thank You!
Blockquote
arrAtdMon = **(ArrayList)**hashTb[unixMon];
if (arrAtdMon != null)
monCount = arrAtdMon.Count;
int[] arrayMax = { monCount, tueCount, wedCount, thuCount, friCount };
int maxValue = arrayMax.Max();
KidAttendance valMon = null;
string monTagName = string.Empty;
Blockquote
above array list is to be sorted it self.
You can do this by implementing IComparer interface:-
public class Ring : IComparer
{
public decimal Price { get; set; }
public int Compare(object x, object y)
{
return ((Ring)x).Price.CompareTo(((Ring)y).Price);
}
}
Working Fiddle.
First, you really should be using the List<T> class, not ArrayList. Doing so wouldn't solve your problem, but it would make the code less fragile and more easy to maintain.
As for the specific question, you want to do something like this…
Assume:
class Ring { public decimal Price { get; set; } }
Then:
ArrayList list = ...; // Initialized as some collection of Ring instances
list.Sort(Comparer.Create((r1, r2) => r1.Price.CompareTo(r2.Price)));
This creates a new Comparer instance using the Comparison<T> of (r1, r2) => r1.Price.CompareTo(r2.Price). That is, for each pair of objects being compared, compare the price of the first with the price of the second.
Assuming that these objects share a base class or an interface with the price property you should be able to do something like this:
// Base class with price property, could also be an shared interface
public abstract class Product
{
public decimal Price{get;set;}
}
public class Ring : Product
{
}
public class Bag : Product
{
}
// Some test data
var myUnsortedArray = new Product[]{new Ring{Price = 1.2m}, new Bag{Price=2.5m}};
// Easy sort with LINQ
var sortedProducts = myUnsortedArray.OrderBy(p => p.Price).ToArray();
var sortedProductsDescending = myUnsortedArray.OrderByDescending(p => p.Price).ToArray();
UPDATE
I just realised that the question is about ArrayLists and have the changed solution below:
// Some test data
var myUnsortedArrayList = new ArrayList{new Ring{Price = 1.2m}, new Bag{Price=2.5m}};
// Easy sort with LINQ
var sortedProducts = myUnsortedArrayList.OfType<Product>().OrderBy(p => p.Price).ToArray();
var sortedProductsDescending = myUnsortedArrayList.OfType<Product>().OrderByDescending(p => p.Price).ToArray();
To sort an set of objects, the object needs to be Comparable and you can set up the comparison you'd like in the CompareTo() method:
IComparable information here

How to sort on the Value of an member of a List<> within a parent List<>

I have a List sort question. I am using c# 3.0 and a generic List structure like this:
public class myObject
{
public int ID { get; set; }
public List<mySetting> setting { get; set; }
}
public class mySetting
{
public int ID { get; set; }
public string Name { get; set; }
public string Value { get; set; } // sort on this!
}
with this structure, I am filling a List of myObject with a LINQ query.
List<myObject> lmo = new List<myObject>();
lmo.SomeFillOperation():
What I want to do now is sort the entire List<myObject> on the individual <mySetting>[].Value values. EDIT: ( So this would be sorting on one keyed index of , for example mySetting[3].Value). I realize I could possibly do it in my SomeFillOperation(), but I want to do it after the List is formed.
Is there a recommended or easy way to do this? Is there a good example you have seen? Thanks in advance!
Well, List<T> already has a Sort method if you want to sort it in place - or you could use LINQ's OrderBy method. OrderBy is slightly easier than Sort:
var sorted = lmo.OrderBy(x => x.Value);
but even Sort isn't too bad:
lmo.Sort((x, y) => x.Value.CompareTo(y.Value));
EDIT: Having read the comment to the question, I no longer understand the question! Leaving this answer here as a potentially useful placeholder while I have dinner...
int MyObjectComparison(MyObject x, MyObject y)
{
return x.setting[0].Value.CompareTo(y.setting[0].Value);
}
lmo.Sort(MyObjectComparison);
Of course, this assumes that you want to use the Value of the first element in setting (and that setting is guarunteed to have at least one element). Solution with less assumption will be forthcoming when more info is given.
Since you are using 3.0, use LINQ:
var newList = lmo.OrderBy(i => i.Value);
and
var newList = lmo.OrderByDescending(i => i.Value);

Categories