简体   繁体   中英

How to sort large numbers stored in a string array?

I need to sort the large numbers stored as string in string array but my algorithm and .net built Array sort method doesn't work.

I tried to convert the number into long or ulong but that throw exception of overflow.

Here is the code that I tried:

string[] unsorted = { "1","2","100","12303479849857341718340192371",
                      "3084193741082937","3084193741082938","111","200" };

for (int index = 0; index < unsorted.Length - 1; index++)
{
    for (int count = 0; count < unsorted.Length - index - 1; count++)
    {
        if (string.Compare(unsorted[count], unsorted[count + 1]) == 1)
        {
            string temp = unsorted[count];
            unsorted[count] = unsorted[count + 1];
            unsorted[count + 1] = temp;
        }
    }
}

Also used the following method:

 Array.Sort(unsorted);

The array should be sorted correctly.

You could use BigInteger.Parse and use Linq's OrderBy on it. For example:

var sorted = unsorted.Select(BigInteger.Parse).OrderBy(e => e).ToArray();

If you need it back as string:

var sorted = unsorted.Select(BigInteger.Parse).OrderBy(e => e).Select(e => e.ToString()).ToArray();

This has a drawback in converting it first to a BigInteger , but probably you need it anyway. However compared to IO and Database access, this nothing adds to a typical application performance.

  • Pro: Readable
  • Contra: Probably not the most efficient solution.

Try following :

string[] unsorted = { "1","2","100","12303479849857341718340192371",
                      "3084193741082937","3084193741082938","111","200" };

var groups = unsorted.OrderBy(x => x.Length).GroupBy(x => x.Length).ToArray();
List<string> results = new List<string>();
foreach (var group in groups)
{
    string[] numbers = group.ToArray();
    for(int i = 0; i < numbers.Count() - 1; i++)
    {
        for(int j = i + 1; j < numbers.Count(); j++)
        {
            if(numbers[i].CompareTo(numbers[j]) == 1)
            {
                string temp = numbers[i];
                numbers[i] = numbers[j];
                numbers[j] = temp;
            }
        }
    }
    results.AddRange(numbers);
}

You don't have an array of numbers, you have an array of strings. So they're being sorted alpha-numerically.

One option would be to use the BigInteger class to store them as numbers:

BigInteger[] unsorted = { 
    BigInteger.Parse("1"),
    BigInteger.Parse("2"), 
    BigInteger.Parse("100"),
    BigInteger.Parse("12303479849857341718340192371"),
    BigInteger.Parse("3084193741082937"),
    BigInteger.Parse("3084193741082938"),
    BigInteger.Parse("111"),
    BigInteger.Parse("200")
};

Failing that, if you want to keep them as strings then you can left-pad them with zeros to make the lengths consistent so the alphanumeric sorting would work:

string[] unsorted = { 
    "00000000000000000000000000001",
    "00000000000000000000000000002",
    "00000000000000000000000000100",
    "12303479849857341718340192371",
    "00000000000003084193741082937",
    "00000000000003084193741082938",
    "00000000000000000000000000111",
    "00000000000000000000000000200"
};

If you choose the former, just change the types in your if block to also be BigInteger as well.

If we want to sort very big numbers stored as strings, without changing string to BigInteger , it's better sort them according to it's length at first and then according to lexicographic order. We can see the sample code below:

using System;
using System.Linq;
public class Test
{
   public static void Main()
   {
     string[] unsorted = { "1","2", "100","12303479849857341718340192371",
                       "3084193741082937","3084193741082938","111","200" };

      unsorted.OrderBy(s => s.Length).ThenBy(s => s);
      Console.WriteLine("Sorted numbers are:");
      foreach (var x in unsorted) {
           Console.WriteLine(x);
      }
   }
}

Note: In order to use OrderBy and ThenBy functionality , we have to include using System.Linq to our program.

对于一个优雅的解决方案,您可以使用linq ,您将拥有具有良好性能的最少代码。

var result = unsorted.Select(e => decimal.Parse(e)).OrderBy(e => e);

The system must be like following. You can transfer values in the array to an arraylist then you can parse them all to BigInteger by for loop. And finally you can sort the list :

BigInteger[] unsorted; 
var bigIntegers = new List<System.Numerics.BigInteger>();

  for (int index = 0; index < unsorted.Length - 1; index++)
  {
  bigIntegers[i] = BigInteger.Parse[i]
  }

bigIntegers.sort();

Another variation:

    static void Main(string[] args)
    {
        List<string> unsorted = new List<string>(new string[] {"1","2","100","12303479849857341718340192371",
                        "3084193741082938","3084193741082937", "111","200" });

        unsorted.Sort((x, y) => (x.Length != y.Length ? x.Length.CompareTo(y.Length) : x.CompareTo(y)));

        foreach(string number in unsorted)
        {
            Console.WriteLine(number);
        }
        Console.Write("Press Enter to quit");
        Console.ReadLine();
    }

Building upon @jdweng's answer , but further reducing it by eliminating the 'manual' bubble sort:

string[] result =
    unsorted.OrderBy(x => x.Length)
    .GroupBy(x => x.Length)
    .SelectMany(x => x.OrderBy(y => y))
    .ToArray();

Or some other variation of the same theme:

using System.Collections.Generic;
using System.Linq;

...

string[] result =
    unsorted.OrderBy(x => x, Comparer<string>.Create((a, b) => a.Length == b.Length ? a.CompareTo(b) : a.Length - b.Length))
    .GroupBy(x => x.Length)
    .SelectMany(x => x)
    .ToArray();

(As noted by @fester's comment underneath @jdweng's answer, this approach will not work reliably if some of the strings are numbers with prepended zeros, such as " 00123 " for example.)

    package com.solution.sorting;

    import java.util.Arrays;
    import java.util.Comparator;

    public class ArraySort {

        public static void main(String[] args) {
            String[] number = { "3", "2", "4", "10", "11", "6", "5", "8", "9", "7" };
            String[] unsorted = { "8", "1", "2", "100", "12303479849857341718340192371", "3084193741082937",
                    "3084193741082938", "111", "200" };

            Arrays.sort(number);
            for (String s : number)
                System.out.println("number="+s);
                //

                Arrays.sort(unsorted, new Comparator<String>() {

                    @Override
                    public int compare(String o1, String o2) {
                        
                        return compareStrings(o1,o2);//Integer.valueOf(o1).compareTo(Integer.valueOf(o2));
                    }

                });
            for (String s : unsorted)
                System.out.println("number1=" + s);

        }

        private static int compareStrings(String s1, String s2) {
            
            //
            if (s1.length() < s2.length()) {
                return -1;
            } else if (s1.length() > s2.length()) {
                return 1;
            }
            for (int i = 0; i < s1.length(); i++) {
                if ((int) s1.charAt(i) < (int) s2.charAt(i))
                    return -1;
                if ((int) s1.charAt(i) > (int) s2.charAt(i))
                    return 1;

            }
            return 0;

        }

    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM