Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 检查字符串是否已排序_C#_.net_String_Linq_Sorting - Fatal编程技术网

C# 检查字符串是否已排序

C# 检查字符串是否已排序,c#,.net,string,linq,sorting,C#,.net,String,Linq,Sorting,我有一个字符串,简化的“12345”,已排序。字符串可能包含数字(0-9)或字母(a-z)。在混合使用的情况下,使用自然排序顺序。我需要一个方法来验证这是否属实 尝试使用linq技术: string items1 = "2349"; //sorted string items2 = "2476"; //not sorted, 6<>7 bool sorted1 = Enumerable.SequenceEqual(items1.OrderBy(x => x), items1)

我有一个字符串,简化的
“12345”
,已排序。字符串可能包含数字(0-9)或字母(a-z)。在混合使用的情况下,使用自然排序顺序。我需要一个方法来验证这是否属实

尝试使用linq技术:

string items1 = "2349"; //sorted
string items2 = "2476"; //not sorted, 6<>7

bool sorted1 = Enumerable.SequenceEqual(items1.OrderBy(x => x), items1); //true
bool sorted2 = Enumerable.SequenceEqual(items2.OrderBy(x => x), items2); //false

检查字符串是否已排序?也许是一些内置的解决方案?

您的解决方案很好,可读性很强。它的一个问题是需要对
字符串
进行排序,这可以通过迭代
字符串
而不排序来解决

var items = "4321";
var sortedItems = items.OrderBy(i => i); // Process the order once only
var sorted = sortedItems.SequenceEqual(items) || sortedItems.SequenceEqual(items.Reverse()); // Reverse using yield return
例如:

var firstDifs = items1.Zip(items1.Skip(1), (x, y) => y - x);
Linq
将第一个
字符串中的每2个项目投影到一个表示其差异的数字,因此如果您有
items1=“1245”
,则输出将为:

firstDifs:
{1,2,1}

现在,您只需验证
firstDifs
是升序还是降序:

bool firstSorted = firstDifs.All(x => x > 0) || firstDifs.All(x => x < 0); //true
boolfirstsorted=firstDifs.All(x=>x>0)| firstDifs.All(x=>x<0)//真的
现在:

  • O(1),因为跳过1个单元格所需的操作量为 不变的
  • O(n)
  • O(n)
所以整个解是O(n)


请注意,使用一个简单的循环将更加有效,同样,如果第一个循环返回了
false
,因为第3487项改变了方向(例如:1234567891),那么第二个循环将无故运行两次(直到需要时)-由于和有两次迭代,
Linq
会对它们进行惰性计算。

我会对所有元素进行简单迭代:

string str = "whatever123";
Func<char, char, bool> pred;
bool? asc = str.TakeWhile((q, i) => i < str.Length - 1)
               .Select((q, i) => str[i] == str[i+1] ? (bool?)null : str[i] < str[i+1])
               .FirstOrDefault(q => q.HasValue);
if (!asc.HasValue)
    return true; //all chars are the same
if (asc.Value)
    pred = (c1, c2) => c1 <= c2;
else
    pred = (c1, c2) => c1 >= c2;

for (int i = 0; i < str.Length - 1; ++i)
{
    if (!pred(str[i], str[i + 1]))
        return false;
}
return true;
var s = "2349"; 
var r = Enumerable.Range(1, s.Length - 1);
//var isAscending = r.All(i => s[i - 1] <= s[i]);
//var isDescending = r.All(i => s[i - 1] >= s[i]);
var isOrdered = r.All(i => s[i - 1] <= s[i]) || r.All(i => s[i - 1] >= s[i]);
string str=“whatever123”;
Func pred;
布尔?asc=str.TakeWhile((q,i)=>istr[i]==str[i+1]?(bool?)null:str[i]q.HasValue);
如果(!asc.HasValue)
返回true//所有的字符都是一样的
if(asc.值)
pred=(c1,c2)=>c1>=c2;
对于(int i=0;i
它需要一个。在C#中,它是。这是O(n)算法

var query = "123abc".Aggregate(new { asceding = true, descending = true, prev = (char?)null }, 
(result, currentChar) =>
    new 
    { 
       asceding = result.prev == null || result.asceding && currentChar >= result.prev, 
       descending = result.prev == null || result.descending && currentChar <= result.prev, 
       prev = (char?)currentChar 
    }
);
Console.WriteLine(query.asceding || query.descending );
聚合(新的{asceding=true,descending=true,prev=(char?)null}, (结果,currentChar)=> 新的 { asceding=result.prev==null | | result.asceding&¤tChar>=result.prev,
descending=result.prev==null | | result.descending&¤tChar我曾经不得不检查一些类似于您的情况,但有大量数据流,因此性能非常重要。我提出了一个性能非常好的小扩展类:

public static bool IsOrdered<T>(this IEnumerable<T> enumerable) where T: IComparable<T>
{
    using (var enumerator = enumerable.GetEnumerator())
    {
        if (!enumerator.MoveNext())
            return true; //empty enumeration is ordered

        var left = enumerator.Current;
        int previousUnequalComparison = 0;

        while (enumerator.MoveNext())
        {
            var right = enumerator.Current;
            var currentComparison = left.CompareTo(right);

            if (currentComparison != 0)
            {
                if (previousUnequalComparison != 0
                    && currentComparison != previousUnequalComparison)
                    return false;

                previousUnequalComparison = currentComparison;
                left = right;
            }
        }
    }

    return true;
}
publicstaticbool已排序(此IEnumerable可枚举),其中T:IComparable
{
使用(var enumerator=enumerable.GetEnumerator())
{
如果(!enumerator.MoveNext())
返回true;//空枚举已排序
var left=枚举数。当前值;
int以前的不相等比较=0;
while(枚举数.MoveNext())
{
var right=枚举数。当前值;
var currentComparison=左。比较到(右);
如果(currentComparison!=0)
{
如果(以前的不平等比较!=0
&&当前比较!=以前的不平等比较)
返回false;
以前的不平等比较=当前比较;
左=右;
}
}
}
返回true;
}
使用它显然非常简单:

var items1 = "2349";
var items2 = "2476"; //not sorted, 6<>7
items1.IsOrdered(); //true
items2.IsOrdered(); //false
var items1=“2349”;
var items2=“2476”//未排序,67
items1.IsOrdered();//true
items2.IsOrdered();//false

不必比较所有元素,您可以比公认的答案做得更好:

string str = "whatever123";
Func<char, char, bool> pred;
bool? asc = str.TakeWhile((q, i) => i < str.Length - 1)
               .Select((q, i) => str[i] == str[i+1] ? (bool?)null : str[i] < str[i+1])
               .FirstOrDefault(q => q.HasValue);
if (!asc.HasValue)
    return true; //all chars are the same
if (asc.Value)
    pred = (c1, c2) => c1 <= c2;
else
    pred = (c1, c2) => c1 >= c2;

for (int i = 0; i < str.Length - 1; ++i)
{
    if (!pred(str[i], str[i + 1]))
        return false;
}
return true;
var s = "2349"; 
var r = Enumerable.Range(1, s.Length - 1);
//var isAscending = r.All(i => s[i - 1] <= s[i]);
//var isDescending = r.All(i => s[i - 1] >= s[i]);
var isOrdered = r.All(i => s[i - 1] <= s[i]) || r.All(i => s[i - 1] >= s[i]);
var s=“2349”;
var r=可枚举范围(1,s.长度-1);
//var isAscending=r.All(i=>s[i-1]s[i-1]>=s[i]);
var-isOrdered=r.All(i=>s[i-1]s[i-1]>=s[i]);

如果字符串包含字母怎么办?您刚刚向我们展示了最好的情况。如果字符不是英文字母(例如
-
)?@c0rd因此
123abc
abc123
ab12cd34
被视为已排序?@user3185569“123abc”或“cba321”有效请定义“更好”.它是“更快”还是“更可读”还是“消耗更少的内存”?你确定要多次迭代吗?ZIP不是只迭代真正需要的元素吗?所以如果我在第三次迭代时发现结果是错误的,所以所有的其余部分都没有迭代,那么其余部分也没有压缩吗?@HaraldDutch压缩将进行两次,因为有两次迭代
All
Linq
惰性地计算它们。@TamirVered
All()
如果发现一个无效字符,则停止处理,直到O(n)对吗?@c0rd如果您有任何重复字符,请更改为
x>=0
,并且
x运算符'>='不能应用于'bool'和'char'类型的操作数。我总是得到
Func
声明错误,我更改了它,请立即尝试OK立即工作,但返回
“aabcdefghijklmnopqrstuvxyz”
false这是因为TODO@c0rd也为您解决了这个问题。
OrderBy
的结果是一个IEnumberable,每次调用都应该处理它。这确实是正确的方法。比任何“简洁”的纯LINQ尝试都要好。DRY和用法更简洁易读。