Làm cách nào để sắp xếp các chuỗi theo thứ tự bảng chữ cái trong khi tính giá trị khi một chuỗi là số?


100

Tôi đang cố gắng sắp xếp một mảng số là chuỗi và tôi muốn chúng sắp xếp theo số.

Vấn đề là tôi không thể chuyển đổi các số thành int .

Đây là mã:

string[] things= new string[] { "105", "101", "102", "103", "90" };

foreach (var thing in things.OrderBy(x => x))
{
    Console.WriteLine(thing);
}

đầu ra: 101, 102, 103, 105, 90

Tôi muốn: 90, 101, 102, 103, 105

CHỈNH SỬA: Đầu ra không được là 090, 101, 102 ...

Đã cập nhật mẫu mã để nói "mọi thứ" thay vì "kích thước". Mảng có thể giống như sau:

string[] things= new string[] { "paul", "bob", "lauren", "007", "90" };

Điều đó có nghĩa là nó cần được sắp xếp theo thứ tự bảng chữ cái và theo số:

007, 90, bob, lauren, paul


8
Tại sao bạn không thể chuyển đổi chúng thành int?
Femaref

1
"kích thước" có thể là một cái gì đó khác như "tên". Mẫu mã chỉ được đơn giản hóa.
sf.

2
Sẽ có bất kỳ số nào là số âm? Tất cả chúng sẽ là số nguyên? Phạm vi của các số nguyên là gì?
Eric Lippert

"things" có thể là bất kỳ loại chuỗi nào. Tôi muốn danh sách được sắp xếp hợp lý cho một người không rành về máy tính. Số âm phải ở trước số dương. Về độ dài chuỗi, nó sẽ không nhiều hơn 100 ký tự.
sf.

5
Bạn muốn đi bao xa? Nên image10đến sau image2? Nên Januaryđến trước February?
svick

Câu trả lời:


104

Chuyển một trình so sánh tùy chỉnh vào OrderBy. Enumerable.OrderBy sẽ cho phép bạn chỉ định bất kỳ trình so sánh nào bạn thích.

Đây là một cách để làm điều đó:

void Main()
{
    string[] things = new string[] { "paul", "bob", "lauren", "007", "90", "101"};

    foreach (var thing in things.OrderBy(x => x, new SemiNumericComparer()))
    {    
        Console.WriteLine(thing);
    }
}


public class SemiNumericComparer: IComparer<string>
{
    /// <summary>
    /// Method to determine if a string is a number
    /// </summary>
    /// <param name="value">String to test</param>
    /// <returns>True if numeric</returns>
    public static bool IsNumeric(string value)
    {
        return int.TryParse(value, out _);
    }

    /// <inheritdoc />
    public int Compare(string s1, string s2)
    {
        const int S1GreaterThanS2 = 1;
        const int S2GreaterThanS1 = -1;

        var IsNumeric1 = IsNumeric(s1);
        var IsNumeric2 = IsNumeric(s2);

        if (IsNumeric1 && IsNumeric2)
        {
            var i1 = Convert.ToInt32(s1);
            var i2 = Convert.ToInt32(s2);

            if (i1 > i2)
            {
                return S1GreaterThanS2;
            }

            if (i1 < i2)
            {
                return S2GreaterThanS1;
            }

            return 0;
        }

        if (IsNumeric1)
        {
            return S2GreaterThanS1;
        }

        if (IsNumeric2)
        {
            return S1GreaterThanS2;
        }

        return string.Compare(s1, s2, true, CultureInfo.InvariantCulture);
    }
}

1
Đối với đầu vào đã cho, điều này tạo ra kết quả giống như câu trả lời của Đệ quy, liên quan đến PadLeft (). Tôi giả định rằng đầu vào của bạn thực sự phức tạp hơn so với ví dụ này cho thấy, trong trường hợp đó, một trình so sánh tùy chỉnh là cách để đi.
Jeff Paulsen

Chúc mừng. Giải pháp này hoạt động và có vẻ là một cách dễ đọc và dễ thực hiện. +1 vì cho tôi thấy bạn có thể sử dụng IComparer trên OrderBy :)
sf.

17
Các IsNumericphương pháp là xấu, một ngoại lệ điều khiển mã hóa phải lúc nào cũng xấu. Sử dụng int.TryParsethay thế. Hãy thử mã của bạn với một danh sách lớn và nó sẽ mất vĩnh viễn.
Nean Der Thal

Nếu nó hữu ích, tôi đã thêm một tiện ích mở rộng vào phiên bản này ở đây để bổ sung hỗ trợ sắp xếp theo từ. Đối với nhu cầu của tôi, tách trên không gian là đủ, và tôi đã có rất ít cần phải lo lắng về những lời sử dụng hỗn hợp (ví dụ test12 vs Test3),
matt.bungard

@NeanDerThal Tôi khá chắc chắn rằng nó chỉ chậm / không tốt khi xử lý rất nhiều ngoại lệ trong một vòng lặp, nếu bạn đang gỡ lỗi hoặc bạn đang truy cập đối tượng Exception.
Kelly Elton

90

Chỉ cần thêm các số 0 vào cùng độ dài:

int maxlen = sizes.Max(x => x.Length);
var result = sizes.OrderBy(x => x.PadLeft(maxlen, '0'));

+1 cho giải pháp đơn giản, nitpicking sẽ (đã được thực hiện trong bản chỉnh sửa, tốt đẹp)
Marino Šimić

Ý tưởng hay nhưng điều tiếp theo là tôi cần phải loại bỏ những giá trị này, vì vậy "90" cần phải là "90", không phải "090"
sf.

6
@sf: Hãy thử nó, bạn có thể thích kết quả. Hãy nhớ rằng, chìa khóa đặt hàng không phải là thứ được đặt hàng. Nếu tôi nói đặt danh sách khách hàng theo họ, thì tôi nhận được danh sách khách hàng chứ không phải danh sách theo họ. Nếu bạn nói sắp xếp thứ tự danh sách các chuỗi theo một chuỗi đã được biến đổi thì kết quả là danh sách có thứ tự của các chuỗi ban đầu, không phải các chuỗi đã được biến đổi.
Eric Lippert

Tôi đã phải thêm "kích thước = kích thước.OrderBy (...)" để làm cho điều này hoạt động. Đó là bình thường hay câu trả lời nên được chỉnh sửa?
gorgabal

1
@gorgabal: Nói chung việc gán lại cho sizescũng không hoạt động, vì kết quả là một kiểu khác. Câu trả lời khá ngắn gọn, trong đó dòng thứ hai hiển thị kết quả dưới dạng một biểu thức, nhưng người đọc phải làm gì đó với nó. Tôi đã thêm một phép gán biến khác để làm rõ hơn điều đó.
đệ quy

74

Và, làm thế nào về điều này ...

string[] sizes = new string[] { "105", "101", "102", "103", "90" };

var size = from x in sizes
           orderby x.Length, x
           select x;

foreach (var p in size)
{
    Console.WriteLine(p);
}

hehe, tôi thực sự thích cái này - rất thông minh. Xin lỗi nếu tôi không cung cấp toàn bộ dữ liệu ban đầu
sf.

3
Điều này cũng giống như tùy chọn pad ở trên chỉ IMO tốt hơn nhiều.
dudeNumber 4

3
var size = Size.OrderBy (x => x.Length) .ThenBy (x => x);
Phillip Davis

1
Nhưng điều này sẽ kết hợp chuỗi chữ cái như thế này: "b", "ab", "101", "103", "bob", "abcd".
Andrew

67

Giá trị là một chuỗi

List = List.OrderBy(c => c.Value.Length).ThenBy(c => c.Value).ToList();

Làm


2
Câu trả lời này là yêu thích của tôi.
LacOniC

2
Cảm ơn tôi vừa phát hiện ra rằng thoát khỏi một phương thức "ThenBy".
ganchito55

Đây hoạt động tuyệt vời đối với trường hợp sử dụng của tôi, nơi mà đầu vào là ở định dạng mớistring[] { "Object 1", "Object 9", "Object 14" }
thelem

2
Đây là câu trả lời tốt nhất. Nó hoạt động và là một học tập tốt. Cảm ơn !!
7 Thứ ba,

1
Nhưng điều này sẽ kết hợp chuỗi chữ cái như thế này: "b", "ab", "101", "103", "bob", "abcd".
Andrew

13

Có một hàm gốc trong cửa sổ StrCmpLogicalWsẽ so sánh số chuỗi dưới dạng số thay vì chữ cái. Thật dễ dàng để tạo một trình so sánh gọi ra hàm đó và sử dụng nó để so sánh.

public class StrCmpLogicalComparer : Comparer<string>
{
    [DllImport("Shlwapi.dll", CharSet = CharSet.Unicode)]
    private static extern int StrCmpLogicalW(string x, string y);

    public override int Compare(string x, string y)
    {
        return StrCmpLogicalW(x, y);
    }
}

Nó thậm chí hoạt động trên các chuỗi có cả văn bản và số. Đây là một chương trình ví dụ sẽ cho thấy sự khác biệt giữa sắp xếp mặc định và StrCmpLogicalWsắp xếp

class Program
{
    static void Main()
    {
        List<string> items = new List<string>()
        {
            "Example1.txt", "Example2.txt", "Example3.txt", "Example4.txt", "Example5.txt", "Example6.txt", "Example7.txt", "Example8.txt", "Example9.txt", "Example10.txt",
            "Example11.txt", "Example12.txt", "Example13.txt", "Example14.txt", "Example15.txt", "Example16.txt", "Example17.txt", "Example18.txt", "Example19.txt", "Example20.txt"
        };

        items.Sort();

        foreach (var item in items)
        {
            Console.WriteLine(item);
        }

        Console.WriteLine();

        items.Sort(new StrCmpLogicalComparer());

        foreach (var item in items)
        {
            Console.WriteLine(item);
        }
        Console.ReadLine();
    }
}

đầu ra nào

Example1.txt
Example10.txt
Example11.txt
Example12.txt
Example13.txt
Example14.txt
Example15.txt
Example16.txt
Example17.txt
Example18.txt
Example19.txt
Example2.txt
Example20.txt
Example3.txt
Example4.txt
Example5.txt
Example6.txt
Example7.txt
Example8.txt
Example9.txt

Example1.txt
Example2.txt
Example3.txt
Example4.txt
Example5.txt
Example6.txt
Example7.txt
Example8.txt
Example9.txt
Example10.txt
Example11.txt
Example12.txt
Example13.txt
Example14.txt
Example15.txt
Example16.txt
Example17.txt
Example18.txt
Example19.txt
Example20.txt

Tôi muốn nó là dễ dàng hơn để sử dụng thư viện hệ thống trong C #
Kyle Delaney

Điều này có thể là hoàn hảo, nhưng không may nó không xử lý các số âm. -1 0 10 2được sắp xếp theo0 -1 2 10
nphx

5

thử cái này

sizes.OrderBy(x => Convert.ToInt32(x)).ToList<string>();

Lưu ý: điều này sẽ hữu ích khi tất cả đều là chuỗi có thể chuyển đổi thành int .....


1
Loại này chuyển đổi chuỗi thành int.
Femaref

1
"kích thước" cũng có thể không phải là số
sf.

Đối với "LINQ to SQL", đừng quên ToList()trước =>sizes.ToList().OrderBy(x => Convert.ToInt32(x))
A. Morel

5

Tôi đoán điều này sẽ tốt hơn nhiều nếu nó có một số số trong chuỗi. Hy vọng nó sẽ giúp ích.

Tái bút: Tôi không chắc về hiệu suất hoặc các giá trị chuỗi phức tạp nhưng nó hoạt động tốt như thế này:

lorem ipsum
lorem ipsum 1
lorem ipsum 2
lorem ipsum 3
...
lorem ipsum 20
lorem ipsum 21

public class SemiNumericComparer : IComparer<string>
{
    public int Compare(string s1, string s2)
    {
        int s1r, s2r;
        var s1n = IsNumeric(s1, out s1r);
        var s2n = IsNumeric(s2, out s2r);

        if (s1n && s2n) return s1r - s2r;
        else if (s1n) return -1;
        else if (s2n) return 1;

        var num1 = Regex.Match(s1, @"\d+$");
        var num2 = Regex.Match(s2, @"\d+$");

        var onlyString1 = s1.Remove(num1.Index, num1.Length);
        var onlyString2 = s2.Remove(num2.Index, num2.Length);

        if (onlyString1 == onlyString2)
        {
            if (num1.Success && num2.Success) return Convert.ToInt32(num1.Value) - Convert.ToInt32(num2.Value);
            else if (num1.Success) return 1;
            else if (num2.Success) return -1;
        }

        return string.Compare(s1, s2, true);
    }

    public bool IsNumeric(string value, out int result)
    {
        return int.TryParse(value, out result);
    }
}

Chính xác những gì tôi đang tìm kiếm. Cảm ơn bạn!
klugerama,

4

Bạn nói rằng bạn không thể chuyển đổi các số thành int vì mảng có thể chứa các phần tử không thể chuyển đổi thành int, nhưng không có hại gì khi thử:

string[] things = new string[] { "105", "101", "102", "103", "90", "paul", "bob", "lauren", "007", "90" };
Array.Sort(things, CompareThings);

foreach (var thing in things)
    Debug.WriteLine(thing);

Sau đó so sánh như thế này:

private static int CompareThings(string x, string y)
{
    int intX, intY;
    if (int.TryParse(x, out intX) && int.TryParse(y, out intY))
        return intX.CompareTo(intY);

    return x.CompareTo(y);
}

Đầu ra: 007, 90, 90, 101, 102, 103, 105, bob, lauren, paul


Btw, tôi đã sử dụng Array.Sort cho đơn giản, nhưng bạn có thể sử dụng cùng một logic trong IComparer và sử dụng OrderBy.
Ulf Kristiansen

Giải pháp này có vẻ nhanh hơn sau đó sử dụng IComparer (ý kiến ​​của tôi). Kết quả 15000 và tôi cảm thấy điều này mang lại sự khác biệt thứ hai.
Jason Foglia

3

Đây có vẻ là một yêu cầu kỳ lạ và xứng đáng là một giải pháp kỳ lạ:

string[] sizes = new string[] { "105", "101", "102", "103", "90" };

foreach (var size in sizes.OrderBy(x => {
    double sum = 0;
    int position = 0;
    foreach (char c in x.ToCharArray().Reverse()) {
        sum += (c - 48) * (int)(Math.Pow(10,position));
        position++;
    }
    return sum;
}))

{
    Console.WriteLine(size);
}

Tất nhiên, ý tôi là 0x30. Ngoài ra, mảng vẫn có thể chứa một chuỗi không phải số, mà giải pháp sẽ tạo ra kết quả thú vị.
Femaref

Và lưu ý rằng -48 hoặc không thay đổi hoàn toàn không có gì, chúng tôi có thể sử dụng trực tiếp giá trị nguyên của ký tự, vì vậy hãy xóa -48 đó nếu nó làm phiền bạn ...
Marino Šimić

Giá trị char là 0x30, nếu bạn chuyển đổi giá trị đó thành int, nó sẽ vẫn là 0x30, không phải là số 0.
Femaref

Thứ duy nhất được chuyển đổi thành số nguyên là số kép được trả về từ Math.Pow
Marino Šimić

femaref nó không quan trọng nếu nó là 0 hay không, hệ thống thập phân sẽ xử lý điều đó, nó có thể là một Đ nếu bạn muốn, điều duy nhất quan trọng là các con số theo thứ tự tăng dần trong bộ ký tự và điều đó ít hơn hơn 10
Marino Šimić

3

Trang web này thảo luận về sắp xếp chữ và số và sẽ sắp xếp các số theo nghĩa logic thay vì theo nghĩa ASCII. Nó cũng tính đến các alpha xung quanh nó:

http://www.dotnetperls.com/alphanumeric-sorting

THÍ DỤ:

  • C: /TestB/333.jpg
  • 11
  • C: /TestB/33.jpg
  • 1
  • C: /TestA/111.jpg
  • 111F
  • C: /TestA/11.jpg
  • 2
  • C: /TestA/1.jpg
  • 111D
  • 22
  • 111Z
  • C: /TestB/03.jpg

  • 1
  • 2
  • 11
  • 22
  • 111D
  • 111F
  • 111Z
  • C: /TestA/1.jpg
  • C: /TestA/11.jpg
  • C: /TestA/111.jpg
  • C: /TestB/03.jpg
  • C: /TestB/33.jpg
  • C: /TestB/333.jpg

Mã như sau:

class Program
{
    static void Main(string[] args)
    {
        var arr = new string[]
        {
           "C:/TestB/333.jpg",
           "11",
           "C:/TestB/33.jpg",
           "1",
           "C:/TestA/111.jpg",
           "111F",
           "C:/TestA/11.jpg",
           "2",
           "C:/TestA/1.jpg",
           "111D",
           "22",
           "111Z",
           "C:/TestB/03.jpg"
        };
        Array.Sort(arr, new AlphaNumericComparer());
        foreach(var e in arr) {
            Console.WriteLine(e);
        }
    }
}

public class AlphaNumericComparer : IComparer
{
    public int Compare(object x, object y)
    {
        string s1 = x as string;
        if (s1 == null)
        {
            return 0;
        }
        string s2 = y as string;
        if (s2 == null)
        {
            return 0;
        }

        int len1 = s1.Length;
        int len2 = s2.Length;
        int marker1 = 0;
        int marker2 = 0;

        // Walk through two the strings with two markers.
        while (marker1 < len1 && marker2 < len2)
        {
            char ch1 = s1[marker1];
            char ch2 = s2[marker2];

            // Some buffers we can build up characters in for each chunk.
            char[] space1 = new char[len1];
            int loc1 = 0;
            char[] space2 = new char[len2];
            int loc2 = 0;

            // Walk through all following characters that are digits or
            // characters in BOTH strings starting at the appropriate marker.
            // Collect char arrays.
            do
            {
                space1[loc1++] = ch1;
                marker1++;

                if (marker1 < len1)
                {
                    ch1 = s1[marker1];
                }
                else
                {
                    break;
                }
            } while (char.IsDigit(ch1) == char.IsDigit(space1[0]));

            do
            {
                space2[loc2++] = ch2;
                marker2++;

                if (marker2 < len2)
                {
                    ch2 = s2[marker2];
                }
                else
                {
                    break;
                }
            } while (char.IsDigit(ch2) == char.IsDigit(space2[0]));

            // If we have collected numbers, compare them numerically.
            // Otherwise, if we have strings, compare them alphabetically.
            string str1 = new string(space1);
            string str2 = new string(space2);

            int result;

            if (char.IsDigit(space1[0]) && char.IsDigit(space2[0]))
            {
                int thisNumericChunk = int.Parse(str1);
                int thatNumericChunk = int.Parse(str2);
                result = thisNumericChunk.CompareTo(thatNumericChunk);
            }
            else
            {
                result = str1.CompareTo(str2);
            }

            if (result != 0)
            {
                return result;
            }
        }
        return len1 - len2;
    }
}

2

Câu trả lời được đưa ra bởi Jeff Paulsen là đúng nhưng Comprarercó thể được đơn giản hóa nhiều cho điều này:

public class SemiNumericComparer: IComparer<string>
{
    public int Compare(string s1, string s2)
    {
        if (IsNumeric(s1) && IsNumeric(s2))
          return Convert.ToInt32(s1) - Convert.ToInt32(s2)

        if (IsNumeric(s1) && !IsNumeric(s2))
            return -1;

        if (!IsNumeric(s1) && IsNumeric(s2))
            return 1;

        return string.Compare(s1, s2, true);
    }

    public static bool IsNumeric(object value)
    {
        int result;
        return Int32.TryParse(value, out result);
    }
}

Điều này hoạt động vì điều duy nhất được kiểm tra cho kết quả của Comparerlà nếu kết quả lớn hơn, nhỏ hơn hoặc bằng 0. Người ta có thể chỉ cần trừ các giá trị cho một giá trị khác và không phải xử lý các giá trị trả về.

Ngoài ra, IsNumericphương pháp không nên sử dụng try-block và có thể được hưởng lợi từ TryParse.

Và đối với những người không chắc chắn: Bộ so sánh này sẽ sắp xếp các giá trị sao cho các giá trị không phải là số luôn được nối vào cuối danh sách. Nếu người ta muốn chúng ở đầu khối thứ hai và thứ ba ifphải được đổi chỗ.


Vì việc gọi phương thức TryParse có thể có một số chi phí, tôi sẽ lưu trữ các giá trị isNumeric cho s1 và s2 thành các giá trị boolean trước tiên và thực hiện so sánh trên các giá trị đó. Bằng cách này, chúng không được đánh giá nhiều lần.
Optavius

1

Thử cái này :

string[] things= new string[] { "105", "101", "102", "103", "90" };

int tmpNumber;

foreach (var thing in (things.Where(xx => int.TryParse(xx, out tmpNumber)).OrderBy(xx =>     int.Parse(xx))).Concat(things.Where(xx => !int.TryParse(xx, out tmpNumber)).OrderBy(xx => xx)))
{
    Console.WriteLine(thing);
}

1
public class NaturalSort: IComparer<string>
{
          [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
          public static extern int StrCmpLogicalW(string x, string y);

          public int Compare(string x, string y)
          {
                 return StrCmpLogicalW(x, y);
          }
}

arr = arr.OrderBy (x => x, new NaturalSort ()). toArray ();

Lý do tôi cần nó là để được lưu trữ trong một thư mục có tên tệp bắt đầu bằng một số:

public static FileInfo[] GetFiles(string path)
{
  return new DirectoryInfo(path).GetFiles()
                                .OrderBy(x => x.Name, new NaturalSort())
                                .ToArray();
}

0
Try this out..  



  string[] things = new string[] { "paul", "bob", "lauren", "007", "90", "-10" };

        List<int> num = new List<int>();
        List<string> str = new List<string>();
        for (int i = 0; i < things.Count(); i++)
        {

            int result;
            if (int.TryParse(things[i], out result))
            {
                num.Add(result);
            }
            else
            {
                str.Add(things[i]);
            }


        }

Bây giờ Sắp xếp danh sách và hợp nhất chúng lại ...

        var strsort = from s in str
                      orderby s.Length
                      select s;

        var numsort = from n in num
                     orderby n
                     select n;

        for (int i = 0; i < things.Count(); i++)
        {

         if(i < numsort.Count())
             things[i] = numsort.ElementAt(i).ToString();
             else
             things[i] = strsort.ElementAt(i - numsort.Count());               
               }

Tôi đã cố gắng đóng góp trong câu hỏi thú vị này ...


0

Giải pháp ưa thích của tôi (nếu tất cả các chuỗi chỉ là số):

// Order by numerical order: (Assertion: all things are numeric strings only) 
foreach (var thing in things.OrderBy(int.Parse))
{
    Console.Writeline(thing);
}

0
public class Test
{
    public void TestMethod()
    {
        List<string> buyersList = new List<string>() { "5", "10", "1", "str", "3", "string" };
        List<string> soretedBuyersList = null;

        soretedBuyersList = new List<string>(SortedList(buyersList));
    }

    public List<string> SortedList(List<string> unsoredList)
    {
        return unsoredList.OrderBy(o => o, new SortNumericComparer()).ToList();
    }
}

   public class SortNumericComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        int xInt = 0;
        int yInt = 0;
        int result = -1;

        if (!int.TryParse(x, out xInt))
        {
            result = 1;
        }

        if(int.TryParse(y, out yInt))
        {
            if(result == -1)
            {
                result = xInt - yInt;
            }
        }
        else if(result == 1)
        {
             result = string.Compare(x, y, true);
        }

        return result;
    }
}

Bạn có thể giải thích mã của bạn? Các câu trả lời chỉ có mã có thể bị xóa.
Wai Ha Lee.

Bài đăng của Jeff Paulsen đã giúp tôi triển khai IComparer <string> để khắc phục sự cố đau nhức của mình. .
kumar

0

Mở rộng câu trả lời của Jeff Paulsen. Tôi muốn đảm bảo không quan trọng số lượng hoặc nhóm char trong chuỗi:

public class SemiNumericComparer : IComparer<string>
{
    public int Compare(string s1, string s2)
    {
        if (int.TryParse(s1, out var i1) && int.TryParse(s2, out var i2))
        {
            if (i1 > i2)
            {
                return 1;
            }

            if (i1 < i2)
            {
                return -1;
            }

            if (i1 == i2)
            {
                return 0;
            }
        }

        var text1 = SplitCharsAndNums(s1);
        var text2 = SplitCharsAndNums(s2);

        if (text1.Length > 1 && text2.Length > 1)
        {

            for (var i = 0; i < Math.Max(text1.Length, text2.Length); i++)
            {

                if (text1[i] != null && text2[i] != null)
                {
                    var pos = Compare(text1[i], text2[i]);
                    if (pos != 0)
                    {
                        return pos;
                    }
                }
                else
                {
                    //text1[i] is null there for the string is shorter and comes before a longer string.
                    if (text1[i] == null)
                    {
                        return -1;
                    }
                    if (text2[i] == null)
                    {
                        return 1;
                    }
                }
            }
        }

        return string.Compare(s1, s2, true);
    }

    private string[] SplitCharsAndNums(string text)
    {
        var sb = new StringBuilder();
        for (var i = 0; i < text.Length - 1; i++)
        {
            if ((!char.IsDigit(text[i]) && char.IsDigit(text[i + 1])) ||
                (char.IsDigit(text[i]) && !char.IsDigit(text[i + 1])))
            {
                sb.Append(text[i]);
                sb.Append(" ");
            }
            else
            {
                sb.Append(text[i]);
            }
        }

        sb.Append(text[text.Length - 1]);

        return sb.ToString().Split(' ');
    }
}

Tôi cũng lấy SplitCharsAndNums từ Trang SO sau khi sửa đổi nó để xử lý tên tệp.


-1

Mặc dù đây là một câu hỏi cũ, nhưng tôi muốn đưa ra giải pháp:

string[] things= new string[] { "105", "101", "102", "103", "90" };

foreach (var thing in things.OrderBy(x => Int32.Parse(x) )
{
    Console.WriteLine(thing);
}

Woha khá đơn giản phải không? : D


-1
namespace X
{
    public class Utils
    {
        public class StrCmpLogicalComparer : IComparer<Projects.Sample>
        {
            [DllImport("Shlwapi.dll", CharSet = CharSet.Unicode)]
            private static extern int StrCmpLogicalW(string x, string y);


            public int Compare(Projects.Sample x, Projects.Sample y)
            {
                string[] ls1 = x.sample_name.Split("_");
                string[] ls2 = y.sample_name.Split("_");
                string s1 = ls1[0];
                string s2 = ls2[0];
                return StrCmpLogicalW(s1, s2);
            }
        }

    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.