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
Related
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.
I have an ArrayList with instances of a class (in this case 'loan'). This loan class contains a variable 'date'. I want to sort my ArrayList by these date variables in the most optimum way.
The way I have done date sorting before, is to use a List<DateTime>. but in this case I want to sort a list/arraylist, keeping the rest of the information, so all the information can be used elsewhere
You can use the System.Linq.Enumerable extension methods Cast<T> and OrderBy for this:
ArrayList list;
List<Loan> loanes = (
from loan in list.Cast<Loan>()
orderby loan.Date
select loan).ToList();
You need to make an IComparer<Loan> that returns x.Date.CompareTo(y.Date).
What Slaks said basically to sort in place in the ArrayList you need a custom IComparer implementation, I put a sample below:
public class Loan
{
public DateTime date { get; set; }
}
public class LoanComparer : IComparer
{
public int Compare(object x, object y)
{
Loan loanX = x as Loan;
Loan loanY = y as Loan;
return loanX.date.CompareTo(loanY.date);
}
}
static void Main(string[] args)
{
Loan l1 = new Loan() {date = DateTime.Now};
Loan l2 = new Loan() { date = DateTime.Now.AddDays(-5) };
ArrayList loans = new ArrayList();
loans.Add(l1);
loans.Add(l2);
loans.Sort(new LoanComparer());
}
Yes, I'm new to c#! :) i'm using .Net4 VS2010.
I have Three classes each one is used to build a list of objects of that type. All three inherit form a base class.
I want to combine the resulting three lists in to one and sort them on one of the base class elements.
Can this be done with lists of different types?
Simplified Example:
Each list is created
public List<TestOne> TestOne list;
public List<TestTwo> TestTwoList;
public List<object> BothLists;
Code to fill TestOne and TestTwo…
What/How do I combine both TestOne and TestTwo into BothLists and sort them on SeqNumber???
public class BaseClassTest
{
public string Loc { get; set; } // loc
// sequence number to order by will be assigned in the resulting class
public int SeqNumber { get; set; }
}
public class TestOne : BaseClassTest
{
public int Number { get; set; }
}
public class TestTwo : BaseClassTest
{
public string CatName { get; set; }
}
You should be able to do:
List<BaseClassTest> sorted = TestOneList.Cast<BaseClassTest>()
.Union(TestTwoList.Cast<BaseClassTest>())
.OrderBy(item => item.SeqNumber)
.ToList();
This will do your sort + union all at once.
"BothLists" should be a List<BaseClassTest>. That should let you sort on base class properties, using .OrderBy(x => x.SequenceNumber).
EDITED TO ADD:
Following up from comments, this should work to combine the lists:
BothLists = TestOneList.OfType<BaseClassList>().Concat().(TestTwoList.OfType<BaseClassList>()).ToList();
Generally, .OfType<>() is preferable to .Cast<>() because it simply filters based on type, rather than forcing a cast.
Given your example this is quite easy:
public List<BaseClassTest> BothLists;
Then you can sort:
BothLists.Sort((a, b) => a.SeqNumber.CompareTo(b.SeqNumber));
If a class inherits from a base, it counts as the base class for most operations. Thus:
List<BaseClassTest> AllTests;
Should get you what you need.
Make TestOne and TestTwo implement the IComparable interface. See here. Then you can combine the lists into an ArrayList and use the Sort method.
List<BaseClassTest> list3 = new List<BaseClassTest>();
list3.AddRange(list1);
list3.AddRange(list2);
var sorted = list3.OrderBy(e => e.SequenceNum).ToList(); //if you really need a list back
This is all assuming you have Linq available. Of course if you do a Union statement might work also.
I have an example class containing two data points:
public enum Sort { First, Second, Third, Fourth }
public class MyClass
{
public MyClass(Sort sort, string name) {
this.Sort = sort;
this.Name = name;
}
public Sort Sort { get; set; }
public string Name { get; set; }
}
I'm looking to sort them into groups by their Sort property, and then alphabetize those groups.
List<MyClass> list = new List<MyClass>() {
new MyClass(MyClass.Sort.Third, "B"),
new MyClass(MyClass.Sort.First, "D"),
new MyClass(MyClass.Sort.First, "A"),
new MyClass(MyClass.Sort.Fourth, "C"),
new MyClass(MyClass.Sort.First, "AB"),
new MyClass(MyClass.Sort.Second, "Z"),
};
The output would then be:
(showing Name)
A
AB
D
Z
B
C
I've been able to do this by using a foreach to separate the items into many smaller arrays (grouped by the enum value) but this seems very tedious - and I think there must be some LINQ solution that I don't know about.
Using extension methods, first OrderBy the enum, ThenBy name.
var sorted = list.OrderBy( m => m.Sort ).ThenBy( m => m.Name );
Aside from the nice LINQ solutions, you can also do this with a compare method like you mentioned. Make MyClass implement the IComparable interface, with a CompareTo method like:
public int CompareTo(object obj)
{
MyClass other = (MyClass)obj;
int sort = this.srt.CompareTo(other.srt);
return (sort == 0) ? this.Name.CompareTo(other.Name) : sort;
}
The above method will order your objects first by the enum, and if the enum values are equal, it compares the name. Then, just call list.Sort() and it will output the correct order.
This should do it, I think
var result = from m in list
orderby m.Sort, m.Name
select m;
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);