C# switch 表达式的超级奇怪行为[重复]

问题描述 投票:0回答:2

我遇到了 C# switch 表达式的一个非常奇怪的行为,我不知道如何解释。所以,我正在练习解决一般面试问题,今天是

Kth Largest Element in an Array
。我在帖子的末尾发布了整个函数,但与问题相关的是函数的最后 5 行,我必须决定是否递归处理数组的左侧或右侧:

return hi - (k - 1) switch
{
    > 0 => FindKthLargest(nums[..hi], k),
    < 0 => FindKthLargest(nums[(hi + 1)..], k - hi - 1),
    _ => nums[hi]
};

我认为它应该做什么:如果

hi
大于
k - 1
那么它递归地与左侧,如果它较小 - 右侧,如果它相等,那么它返回具有该索引的元素。它看起来非常简单,但并没有按预期工作。它不仅不起作用,而且会产生非常奇怪的结果。例如,对于输入
nums = [3, 2, 1, 5, 6, 4]
k = 2
,该函数在我的本地计算机上返回
8
,这甚至不在数组中(并且您可以验证代码仅返回数组元素)。

无论如何,在摆弄它之后,我发现这个稍微修改过的代码确实有效:

var wtf = hi - (k - 1);
return wtf switch
{
    > 0 => FindKthLargest(nums[..hi], k),
    < 0 => FindKthLargest(nums[(hi + 1)..], k - hi - 1),
    _ => nums[hi]
};

完全相同,但条件被移至单独的变量中。那么那里发生了什么?

函数全文:

public int FindKthLargest(Span<int> nums, int k) 
{
    if (nums.Length == 1)
        return nums[0];

    var r = Random.Shared.Next(nums.Length);
    (nums[0], nums[r]) = (nums[r], nums[0]);
    int lo = 1, hi = nums.Length - 1, v = nums[0];
    while(true)
    {
        while (lo < hi && nums[lo] > v) lo++;
        while (nums[hi] < v) hi--;
        if (lo >= hi)
            break;
        (nums[lo], nums[hi]) = (nums[hi], nums[lo]);
        lo++; hi--;
    }
    (nums[0], nums[hi]) = (nums[hi], nums[0]);

    var wtf = hi - (k - 1);
    return wtf switch
    {
        > 0 => FindKthLargest(nums[..hi], k),
        < 0 => FindKthLargest(nums[(hi + 1)..], k - hi - 1),
        _ => nums[hi]
    };

    //this works too:
    /*        
    if (hi == k - 1)
        return nums[hi];
    return hi > k - 1 ? 
        FindKthLargest(nums[..hi], k) : 
        FindKthLargest(nums[(hi + 1)..], k - hi - 1);
    */
}
c# arrays recursion pattern-matching switch-expression
2个回答
2
投票
return hi - (k - 1) switch
{
    ...
};

这被解析为:

hi - ((k - 1) switch
{ 
    ...
});

也就是说,它查看

k - 1
,打开结果,然后从
hi
中减去该结果。

你想要:

return (hi - (k - 1)) switch
{
    ...
}

1
投票

此行为由表达式/运算符优先级决定。更改为:

return (hi - (k - 1)) switch
{
    > 0 => FindKthLargest(nums[..hi], k),
    < 0 => FindKthLargest(nums[(hi + 1)..], k - hi - 1),
    _ => nums[hi]
};

否则解析为:

hi - ((k-1) switch {...})

比较 hi - k + 1 switch

hi - (k - 1) switch
(hi - k + 1) switch
 的反编译 (@sharplab.io)

另请检查运算符优先级文档,其中:

switch
/
with
switch
with
表达式

优先级高于:

x + y
x – y
:添加剂

© www.soinside.com 2019 - 2024. All rights reserved.