简体   繁体   English

C#-如何对包含文本和数字的字符串进行排序

[英]C# - How to sort strings that include text and numbers

I have a listview that is filled with computernames and usernames and a number(as string). 我有一个列表视图,其中充满了计算机名和用户名以及一个数字(作为字符串)。 I already created my own ListViewItemComparer using the IComparer interface. 我已经使用IComparer接口创建了自己的ListViewItemComparer。 But it doesn´t sort the items correctly like how I want. 但是它不能像我想要的那样正确地对项目进行排序。 This is how it should sort the computers for example: Computer-1 Computer-2 Computer-3 ... Computer-15 例如,这就是它应该如何对计算机进行排序:Computer-1 Computer-2 Computer-3 ... Computer-15

and this is how it sorts them: Computer-1 Computer-10 Computer-11 ... Computer-2 Computer-3 这是它们的排序方式:计算机1计算机10计算机11计算机...计算机2计算机3

The problem is that i can´t simply cut the "computer-" part out and compare the numbers that follows as this was just an example and the computernames can be everything(aaa393bbb333, ccccvvvv, 222hhhdh,Computer-01, Computer-02,....) 问题是我不能简单地剪掉“计算机”部分,然后比较后面的数字,因为这只是一个例子,计算机名可以是所有内容(aaa393bbb333,ccccvvvv,222hhhdh,Computer-01,Computer-02, ....)

This is my code: 这是我的代码:

 private bool isNumeric(String pInput)
    {
        int o;
        return int.TryParse(pInput, out o);
    }

    public int Compare(object x, object y)
    {
        ListViewItem itemX = x as ListViewItem;
        ListViewItem itemY = y as ListViewItem;
        //
        int returnVal = -1;
        if (itemX == null && itemY == null) returnVal = 0;
        else if (itemX == null) returnVal = -1;
        else if (itemY == null) returnVal = 1;
        else if (itemX.SubItems.Count - 1 < col && itemY.SubItems.Count - 1 < col) returnVal = 0;
        else if (itemX.SubItems.Count - 1 < col) returnVal = -1;
        else if (itemY.SubItems.Count - 1 < col) returnVal = 1;
        else if(isNumeric(itemX.SubItems[col].Text) && isNumeric(itemY.SubItems[col].Text))
        {
            //used for number comparison
            int value1 = int.Parse(itemX.SubItems[col].Text);
            int value2 = int.Parse(itemY.SubItems[col].Text);
            if (value1 == value2) returnVal = 0;
            else if (value1 < value2) returnVal = -1;
            else if (value1 > value2) returnVal = 1;
        }
        else returnVal = String.Compare(itemX.SubItems[col].Text, itemY.SubItems[col].Text);
        if (order == SortOrder.Descending)
            returnVal *= -1;
        return returnVal;
    }

You could use the regex expression 您可以使用正则表达式

(?<=\D)(?=\d)|(?<=\d)(?=\D)

to split the string into numbers and text. 将字符串拆分为数字和文本。

string[] parts = Regex.Split(theString, @"(?<=\D)(?=\d)|(?<=\d)(?=\D)");

This yields alternately numbers and texts. 这样交替产生数字和文本。 How it works: 这个怎么运作:

(?<=exp)pos      Match any position pos following a prefix exp. 
pos(?=exp)       Match any position pos preceding a suffix exp. 

So the regex means, split at a position between text and number or at a position between number and text where \\D stands for a non-digit character, \\d for a digit character and | 因此,正则表达式的意思是,在\\D代表非数字字符, \\d代表数字字符, |分隔在文本和数字之间或在数字和文本之间的位置| for OR. 或。

You will have to test whether the first part is a text or a number with 您将必须使用以下命令测试第一部分是文本还是数字

bool firstIsNumber = Char.IsDigit(parts[0][0]);

If the first part is a number, all parts at even indexes are numbers and all parts at odd indexes are texts and vice versa. 如果第一部分是数字,则偶数索引的所有部分都是数字,奇数索引的所有部分都是文本,反之亦然。

private static readonly Regex numTextSplitRegex =
    new Regex(@"(?<=\D)(?=\d)|(?<=\d)(?=\D)", RegexOptions.Compiled);

public int Compare(string x, string y)
{
    x = x ?? "";
    y = y ?? "";
    string[] xParts = numTextSplitRegex.Split(x);
    string[] yParts = numTextSplitRegex.Split(y);

    bool firstXIsNumber = xParts[0].Length > 0 && Char.IsDigit(xParts[0][0]);
    bool firstYIsNumber = yParts[0].Length > 0 && Char.IsDigit(yParts[0][0]);

    if (firstXIsNumber != firstYIsNumber) {
        return x.CompareTo(y);
    }

    for (int i = 0; i < Math.Min(xParts.Length, yParts.Length); i++) {
        int result;
        if (firstXIsNumber == (i % 2 == 0)) { // Compare numbers.
            long a = Int64.Parse(xParts[i]);
            long b = Int64.Parse(yParts[i]);
            result = a.CompareTo(b);
        } else { // Compare texts.
            result = xParts[i].CompareTo(yParts[i]);
        }
        if (result != 0) {
            return result;
        }
    }
    return xParts.Length.CompareTo(yParts.Length);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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