ArrayList sorting

  • Thread starter Thread starter Mark
  • Start date Start date
M

Mark

Does anyone know of a way to do multicolumn sorting with the ArrayList
object?

Basically I have a collection of objects and I want to sort on multiple
properties of the objects in the collection.

Any guidance here would be great.

Thanks.
 
Mark said:
Does anyone know of a way to do multicolumn sorting with the ArrayList
object?

Basically I have a collection of objects and I want to sort on multiple
properties of the objects in the collection.

Any guidance here would be great.

Thanks.

You need to implement the IComparable interface on your object, which
defines a single "CompareTo" method. The implementation would look something
like this (example sorts on two properties only):

Given a class called "Person" containing a "FirstName" and a "LastName"
property, and we would like to sort by LastName and then FirstName.

public class Person : IComparable
{
<implementation of constructor/properties/etc>

public int CompareTo(object obj)
{
// compare the first property of each object (returns 0 if the two
objects match)
int result = this.LastName.CompareTo(((Person)obj).LastName) == 0;
if(result == 0) // if the first property matched, we'll do a second
comparison
{
// compare the second property of each object
result = this.FirstName.CompareTo(((Person)obj).FirstName);
}
return result;
}
}

Good luck.
 
Mark said:
Does anyone know of a way to do multicolumn sorting with the ArrayList
object?

Basically I have a collection of objects and I want to sort on multiple
properties of the objects in the collection.

Any guidance here would be great.

Use the version of ArrayList.Sort which takes an IComparer - that way
you can have different IComparers to sort by different columns. You can
also have a "combining" IComparer which is set up to have an ordered
sequence of other ones, to sort by multiple columns at the same time,
as it were.
 
Hi,
this implementation lets you sort by n number of columns and each column can be ascending or descending. The only limitation is that the sort type must be specified before ascendiong/desending


1) define the sorting class.
2) define the contents of the array
3) create an instance of the sorting class
4) specify columns and ascend/desend
5) sort


// ==================================================
///
/// class to compare search results by multiple columns
/// NOTE:
///
/// The SortType MUST be specified BEFORE Ascend
///
///
public class ItemElementSort : IComparer
{
///
/// sort order
///
public enum SortType
{
byName,
bySelected,
byChecked,
};

private ArrayList ascendType = new ArrayList();
private ArrayList srtOrders = new ArrayList();

// ==================================================
private SortType _st;
///
/// Property for sort type
///
public SortType sortType
{
get
{
return _st;
}
set
{
_st = value;
Int32 index = srtOrders.IndexOf(_st);
if (index > -1)
{
srtOrders.Remove(index);
ascendType.Remove(index);

}
srtOrders.Insert(0, _st);
ascendType.Insert(0, Ascend);
}
}

// ==================================================
private bool _Ascend = true;
///
///
///
public bool Ascend
{
get { return _Ascend; }
set
{
_Ascend = value;
if (ascendType.Count > 0)
{
ascendType[0] = value;
}
}
}

// ==================================================
///
/// Constructor with SortType
///
///
///
public ItemElementSort(SortType srtType, bool ascend)
{
sortType = srtType;
Ascend = ascend;
}
// ==================================================
///
/// Default Contructor
///
public ItemElementSort()
{
}

// ==================================================
///
/// Compare 2 ListItems
///
/// first category
/// second category
/// the lesser value
Int32 IComparer.Compare(Object x, Object y)
{
int index = 0;
Int32 result;
SortType sortType;
bool ascend;

do
{
sortType = (SortType)srtOrders[index];
ascend = (bool)ascendType[index];
result = Compare(x, y, sortType, ascend);
index++;
} while ((result == 0) && (index < srtOrders.Count));
return result;
}

///
/// Compare two fields of sort type
///
///
///
///
///
///
Int32 Compare(Object x, Object y, SortType stype, bool ascend)
{
ItemElement a = (ItemElement)x;
ItemElement b = (ItemElement)y;

switch (stype)
{
case SortType.byName:
return Cmp(a.Text, b.Text, ascend);

case SortType.bySelected:
return Cmp(a.Selected, b.Selected, ascend);

case SortType.byChecked:
return Cmp(a.Checked, b.Checked, ascend);

default:
string strErr = "InvalidSort";
throw new ArgumentException(strErr, sortType.ToString());
//break;
}
}

// ==================================================
///
///
///
///
///
///
private Int32 Cmp(string a, string b, bool ascend)
{
string str1 = "";
string str2 = "";
if (a is object)
{
str1 = a;
}
else
{
str1 = "";
}
if (b is object)
{
str2 = b;
}
else
{
str2 = "";
}
if (ascend)
{
return string.Compare(str1, str2, true);
}
return string.Compare(str2, str1, true);
}

// ==================================================
///
///
///
///
///
///
private Int32 Cmp(bool a, bool b, bool ascend)
{
if (a == b)
{
return 0;
}
return (a == false) ? ((ascend) ? 1 : -1) : ((ascend) ? -1 : 1);
}

}



public class ItemElement
{
private string _Text;
public string Text
{
get { return _Text; }
set { _Text = value; }
}

private bool _Selected = false;
public bool Selected
{
get { return _Selected; }
set { _Selected = value; }
}
private bool _Checked = false;
public bool Checked
{
get { return _Checked; }
set { _Checked = value; }
}

}



then in your code to use this to sort byName ascending then by bySelected decending

assume Listbox contains an array of ItemElement


private readonly ItemElementSort ElementSort =
new ItemElementSort(ItemElementSort.SortType.bySelected, true);
ElementSort.SortType = byName;

ElementSort.Ascend = false;
this.ListBox.Items.Sort(ElementSort);
this.ListBox.Refresh();



Paul
 
Last edited:
Back
Top