11

I have an ArrayList that contains,

[0] = "1"
[1] = "10"
[2] = "2"
[3] = "15"
[4] = "17"
[5] = "5"
[6] = "6"
[7] = "27"
[8] = "8"
[9] = "9"

Now i need to sort the array list such that it becomes,

[0] = "1"
[1] = "2"
[2] = "5"
[3] = "6"
[4] = "8"
[5] = "9"
[6] = "10"
[7] = "15"
[8] = "17"
[9] = "27"

At last i will be getting the values from ArrayList and using them as 'int' values. How can i do this? Or shall i convert them to int at first and then sort them.?

1
  • What version of C# are you using? What version of Visual Studio? If you're not using .NET 1.1, then you should not be using ArrayList. Instead, you should use List<T>. In your case, that looks like List<string>. Commented May 12, 2009 at 12:25

10 Answers 10

16

If you can be sure the list contains only strings that can be transformed to integers, then with the IEnumerable<T>.OrderBy extension method, try this:

var sortedList = list.OrderBy(item => int.Parse(item));

If you're using an ArrayList instead of a List<string> (boo!), you'll need to Cast first:

var sortedList = list.Cast<string>().OrderBy(item => int.Parse(item));

You can also define your own comparer as JaredPar noted, but IMO that's a lot of work for something that's already implemented. However, it's more efficient.

Sign up to request clarification or add additional context in comments.

2 Comments

This won't work. The OP is using an ArrayList. You need at least a .Cast<string> in there.
And it seems that Linq is required.
6

There are numerous sort methods in the framework including ArrayList.Sort. The problem is that they are all going to sort alphabetically and not numerically. You'll need to write a custom sorter that understands numeric sorts.

Try the following (some argument checking left out for brevity)

public class NumericComparer : IComparer {
  public int Compare(object x, object y) {
    string left = (string)x; 
    string right = (string)y;
    int max = Math.Min(left.Length, right.Length);
    for ( int i = 0; i < max; i++ ) {
      if ( left[i] != right[i] ) { 
        return left[i] - right[i];
      }
    }
    return left.Length - right.Length;
  }
}

list.Sort(new NumericComparer());

8 Comments

Why still compare it like strings? they are all numbers?? isn't easy to just parse them as int and return the result?
He's going to say it's less efficient to do it that way
@gbianchi, @Sean is correct. The reason I did a char comparison is that it's much more efficient to do this than to parse into numbers and compare. Parsing into numbers works great but it has a noticable performance difference than doing char comparisions
Yes, it's more efficient to compare the strings character-by-character. Less readable, though! ;)
You said that a for with an if with a call to math.min and a re cast to string is speeder that just a parse? I really need to try it... Also if your number are bigger this is still more performant?
|
6

Implement custom comparer and pass it to ArrayList.Sort()

Complete Code:

using System;
using System.Collections;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            ArrayList a = new ArrayList();
            a.Add("1");
            a.Add("13");
            a.Add("3");
            a.Add("25");
            a.Add("2");
            a.Add("12");
            a.Sort(new CustomComparer());

            foreach (String s in a)
                Console.WriteLine(s);

            Console.Read();
        }


    }

    public class CustomComparer : IComparer
    {
        Comparer _comparer = new Comparer(System.Globalization.CultureInfo.CurrentCulture);

        public int Compare(object x, object y)
        {
            // Convert string comparisons to int
            return _comparer.Compare(Convert.ToInt32(x), Convert.ToInt32(y));
        }
    }
}

Output:

1 2 3 12 13 25

2 Comments

I think it's a bit complicated for what the user wants, but it would do the trick, I think.
It will do the trick thats for sure. And once CustomComparer is created, user can just add it as a parameter to sort wherever he needs to sort the string literals in numeric order.
4

Maybe you could store the values in a strongly typed list like List instead, and the, if necessary, convert them to string, when cosuming them. Like this:

        List<int> intList = new List<int>(new int[] {3, 2, 1});

        intList.Sort();

        foreach (int theInt in intList)
        {
            System.Diagnostics.Debug.WriteLine(theInt.ToString());
        }

1 Comment

As a side note, don't declare it as an IList<int> or you'll be bitten by List having Sort() while IList doesn't.
1

You'll be better of creating another array with Int values and then sorting it with ArrayList.Sort(). You could call ArrayList.Sort() and pass it a delegate that will compare those strings as numbers but it will be slower. How much slower depends on size of your array and I personally think for sizes less then 100 it doesn't really matter.

Comments

0

If the values are all ints then why not store them as ints? That would make sorting easier and faster.

In what other ways are the values used? If they're only used as strings and only sorted once then it's probably sensible to leave them as they are - as strings.

On the other hand, if they're used in maths ops then it's best to store them as ints.

Comments

0
 List<int> liDllCnt = new List<int>();
 for (int temp = 0; temp < alFileName.Count; temp++)
     liDllCnt.Add(Int32.Parse(alFileName[temp].ToString()));
 liDllCnt.Sort();

alFileName is the name of the arraylist that i used.

1 Comment

Is this is your solution then you really need to store the data as int.
0

This is the safest way

aryList is your ArrayList instance

                object[] list = aryList.ToArray();
                Array.Sort<object>
                    (
                        list,
                        delegate(object x, object y)
                        {
                            int a = 0, b = 0;
                            if (x == y) return 0;
                            if (x == null || y == null)
                                return x == null ? -1 : 1;
                            int.TryParse(x.ToString(), out a);
                            int.TryParse(y.ToString(), out b);
                            return a.CompareTo(b);
                        }
                    );

result saved into "list" object array

Comments

0

If you can get the ArrayList items into a strongly typed container such as List<String> or String[] then Linq makes it easy to do the rest. The following implementation parses the string values only once and creates an anonymous type for each with the original string and its integer value.

public void Test_SortArrayList()
{
    ArrayList items = new ArrayList(new []{"1", "10", "2", "15", "17", "5", "6", "27", "8", "9"});
    string[] strings = (string[])items.ToArray(typeof(string));
    List<string> result = strings
        .Select(x => new
            {
                Original = x,
                Value = Int32.Parse(x)
            })
        .OrderBy(x => x.Value)
        .Select(x => x.Original)
        .ToList();
    result.ForEach(Console.WriteLine);
}

Comments

0

Arraylist Sort(CaseSensitive) in Ascending Order Helpful for someone

class ArrayCaseSensitive:IComparer
    {
        int IComparer.Compare(object x, object y)
        {
            return (new CaseInsensitiveComparer().Compare(x,y));
        }

    public static void Main(string[] args)
    {
            IComparer sc = new ArrayCaseSensitive();
           
        ArrayList arr = new ArrayList();
        arr.Add("AB");
        arr.Add("bc");
        arr.Add("1");
        arr.Sort(sc);
        foreach(var strs in arr)
        {
            Console.WriteLine(strs);
        }
        
    }

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.