从.Net中的多个字符串创建可排序字符串

时间:2011-02-10 22:22:11

标签: c# .net string

我需要一个函数将一个字符串数组转换为一个字符串,该字符串可以按照与排序输入相同的顺序排序(排序第一个输入参数,如果等于排序第二个等等......)

在本机代码中,用\ 0分隔字符串会有,但不知何故

(“a”+ char.MinValue +“2”)。CompareTo(“a1”)等于1!

发生了什么,是否可以创建这样的功能?

public static string StringsToKey(params string[] values)

编辑:这是我想要成功的测试:

Assert.IsTrue(MiscUtils.StringsToKey("a", "2").CompareTo(MiscUtils.StringsToKey("a1")) < 0);

我想避免使用CompareOrdinal,因为我并不总是控制密钥的排序方式。此外,序数可能会在国际集上产生错误的排序顺序......

5 个答案:

答案 0 :(得分:5)

public static string StringsToKey(params string[] values)
{
    return string.Join(char.MinValue.ToString(), values);
}

用法应该有效:

var s1 = StringsToKey("abc", "def", "1234");
var s2 = StringsToKey("ab", "cde", "f1234");

var comparisonResult = string.Compare(s1, s2, StringComparison.Ordinal);

修改

var s1 = StringsToKey("a", "2");
var s2 = StringsToKey("a1");

var r = string.Compare(s1, s2, StringComparison.Ordinal);

返回负值(-49)。

编辑II:

正如Joe在评论中提到的那样,如果字符串包含'\0'(如果tab用作分隔符,则为'\t'),这将不起作用。因此,没有这样的分隔符适用于所有情况。所以,我重写了该函数,但现在它有2个参数,但仍然使用CompareTo方法进行比较:

public static int CompareStringSequences(
    IEnumerable<string> first, 
    IEnumerable<string> second)
{
    var x = Enumerable.Zip(first, second, (s1, s2) => s1.CompareTo(s2))
        .FirstOrDefault(i => i != 0);

    return x == 0 ?
               x1.Length - x2.Length :
               x;
}

答案 1 :(得分:1)

String.CompareTo()方法返回一个int,将两个值与最短字符串的长度进行比较。假设'\ 0'是“小于”字符'1',它以正常的字符串顺序跟随它。您可以使用String.Split()方法拆分任何字符。包括'\ 0'。然后,您可以使用Array.Sort()方法对字符串进行排序。

答案 2 :(得分:1)

基本上,如果使用“序数排序”,您想要的操作就是简单地连接所有字符串。为了说明,我们采用两个字符串数组:

a={"My", "dog", "is",     "black"}
b={"My", "cat", "sleeps", "often"}

比较这些数组中的每个字符串,直到找到不同的字符串:

a={"My", "dog", "is",     "black"}
b={"My", "cat", "sleeps", "often"}
          ^
          first difference: b is "less than" a

...完全等于比较连接的字符串:

a="Mydogisblack"
b="Mycatsleepsoften"
     ^
     First difference; again, b < a

您方法的代码就是:

public static string StringsToKey(params string[] values)
{
    var builder = new StringBuilder();
    foreach(var s in values)
        builder.Append(s + "\0"); //the \0 is ASCII 0, used to delimit words
    return builder;
}

答案 3 :(得分:1)

此代码似乎适用于输入不包含标签的情况:

    public static string StringsToKey(params string[] values)
    {
        return values.Aggregate("", (current, value) => current + value + '\t');
    }

答案 4 :(得分:1)

与以null结尾的C样式字符串不同,.NET字符串可能包含空字符,因此在一般情况下,没有分隔符可以保证排序低于字符串中的任何有效字符。

当然,如果您确定您的字符串不包含空值并且顺序排序正常,则已发布的某些解决方案将起作用。

但我会说甚至不尝试。为字符串数组编写比较器将更有效(避免创建临时字符串)并更好地表达您的意图。有很多方法可以做到这一点,包括以下内容(比较IList&lt; string&gt;而不是string []以获得更大的灵活性,并支持文化敏感的比较):

public class StringListComparer : IComparer<IList<string>>
{
    private StringComparer comparer;

    public StringListComparer()
        : this(StringComparer.Ordinal)
    {
    }

    public StringListComparer(StringComparer comparer)
    {
        if (comparer == null) throw new ArgumentNullException("comparer");
        this.comparer = comparer;
    }

    public int Compare(IList<string> x, IList<string> y)
    {
        int result;
        for (int i = 0; i < Math.Min(x.Count, y.Count); i++)
        {
            result = comparer.Compare(x[i], y[i]);
            if (result != 0) return result;
        }
        return x.Count.CompareTo(y.Count);
    }
}

以上代码未经测试且可能有错误,但我相信你明白了。