Chuyển đổi trường hợp: tôi có thể sử dụng một dải ô thay vì một số không


86

Tôi muốn sử dụng switch, nhưng tôi gặp nhiều trường hợp, có phím tắt nào không? Cho đến nay, giải pháp duy nhất tôi biết và đã thử là:

switch (number)
{
case 1: something; break;
case 2: other thing; break;
...
case 9: .........; break;
}

Những gì tôi hy vọng mình có thể làm là:

switch (number)
{
case (1 to 4): do the same for all of them; break;
case (5 to 9): again, same thing for these numbers; break;
}

1
Bạn có thể sử dụng if-else cho trường hợp như vậy
Satpal 22/1113

Câu trả lời:


226

Hơi muộn đối với trò chơi cho câu hỏi này, nhưng trong các thay đổi gần đây được giới thiệu trong C # 7 (Có sẵn theo mặc định trong Visual Studio 2017 / .NET Framework 4.6.2), hiện có thể chuyển đổi dựa trên phạm vi với switchcâu lệnh.

Thí dụ:

int i = 63;

switch (i)
{
    case int n when (n >= 100):
        Console.WriteLine($"I am 100 or above: {n}");
        break;

    case int n when (n < 100 && n >= 50 ):
        Console.WriteLine($"I am between 99 and 50: {n}");
        break;

    case int n when (n < 50):
        Console.WriteLine($"I am less than 50: {n}");
        break;
}

Ghi chú:

  • Dấu ngoặc đơn ()không bắt buộc trong whenđiều kiện, nhưng được sử dụng trong ví dụ này để làm nổi bật (các) phép so sánh.
  • varcũng có thể được sử dụng thay cho int. Ví dụ: case var n when n >= 100:.

10
Ngài là người hùng của tôi. Tôi muốn nhấn mạnh điều này bằng một số từ chửi thề, nhưng không phải vậy. :)
Gawie Greef

2
Điều kiện ()xung quanh whenlà không cần thiết. Tức case int n when n >= 100:là cũng hoạt động.
Uwe Keim

6
Thậm chí varkhông hoạt động: Tức là case var n when n >= 100:.
Uwe Keim

9
@JamesKo Tôi nghĩ nó rõ ràng và cải thiện khả năng đọc so với một loạt các câu lệnh if, đặc biệt nếu bạn có nhiều hơn 3-4 điều kiện.
Sách

1
Vượt trội hơn nhiều so với một loạt các câu lệnh if, nó rõ ràng hơn nhiều.
John Stock

44

Đây là một giải pháp tốt hơn và thanh lịch cho tuyên bố vấn đề của bạn.

int mynumbercheck = 1000;
// Your number to be checked
var myswitch = new Dictionary <Func<int,bool>, Action>
            { 
             { x => x < 10 ,    () => //Do this!...  },  
             { x => x < 100 ,    () => //Do this!...  },
             { x => x < 1000 ,    () => //Do this!...  },
             { x => x < 10000 ,   () => //Do this!... } ,
             { x => x < 100000 ,  () => //Do this!... },
             { x => x < 1000000 ,  () => //Do this!... } 
            };

Bây giờ để gọi công tắc có điều kiện của chúng tôi

   myswitch.First(sw => sw.Key(mynumbercheck)).Value();

Thay thế cho Switch / ifElse


1
@Akxaya Tôi vẫn nghĩ rằng công tắc nên được mở rộng trong C #, nhưng điều này trông tuyệt vời và có vẻ hoạt động thực sự tốt. Thực sự đánh giá cao bạn chia sẻ ví dụ này. Cảm ơn bạn
WonderWorker

Đây không phải là câu trả lời rõ ràng cho phạm vi trong câu hỏi chuyển đổi / trường hợp.
Pointer Null

13
Từ điển không lưu trữ và trả về các giá trị theo thứ tự chúng được thêm vào. Điều này xảy ra với trình biên dịch của Microsoft, nhưng người ta có thể dễ dàng viết trình biên dịch phù hợp khi nó không hoạt động. Thay vào đó, hãy sử dụng List <KeyValuePair <Func <int, bool>, Action >>. Cũng lưu ý rằng có một khoản chi phí để tạo cấu trúc dữ liệu và vì vậy nó có thể phải là một thành viên chỉ đọc tĩnh.
Nathan Phillips

@PointerNull: vui lòng tham khảo blog để biết mã cần thiết được viết trong nhận xét để tham khảo trong tương lai
Akxaya

@NathanPhillips: cảm ơn vì đã giới thiệu điều này. đặc biệt, bộ sưu tập IList cũng sẽ là một giải pháp thay thế. đây chỉ là một mẫu tôi đã triển khai với các tham số phức tạp bằng cách sử dụng List <t>.
Akxaya

13

Tôi sẽ sử dụng các toán tử bậc ba để phân loại các điều kiện chuyển đổi của bạn.

Vì thế...

switch( number > 9 ? "High" :
        number > 5 ? "Mid" :
        number > 1 ? "Low" : "Floor")
        {
              case "High":
                    do the thing;
                    break;
               case "Mid":
                    do the other thing;
                    break;
               case "Low":
                    do something else;
                    break;
               case "Floor":
                    do whatever;
                    break;
         }

12

Để hoàn thành chuỗi, đây là cú pháp với C # 8:

  var percent = price switch
  {
    var n when n >= 1000000 => 7f,
    var n when n >= 900000 => 7.1f,
    var n when n >= 800000 => 7.2f,
    _ => 0f // default value
  };

Nếu bạn muốn chỉ định các phạm vi:

  var percent2 = price switch
  {
    var n when n >= 1000000 => 7f,
    var n when n < 1000000 && n >= 900000 => 7.1f,
    var n when n < 900000 && n >= 800000 => 7.2f,
    _ => 0f // default value
  };

8

If-else nên được sử dụng trong trường hợp đó, Nhưng nếu vẫn cần chuyển đổi vì bất kỳ lý do gì, bạn có thể làm như bên dưới, các trường hợp đầu tiên không có ngắt sẽ truyền cho đến khi gặp ngắt đầu tiên. Như các câu trả lời trước đã đề xuất, tôi khuyên bạn nên chuyển đổi if-else.

switch (number){
            case 1:
            case 2:
            case 3:
            case 4: //do something;
                    break;
            case 5:
            case 6:
            case 7:
            case 8:
            case 9: //Do some other-thing;
                   break;
        }

8

Bạn có thể switchtạo phạm vi "xử lý" bằng cách sử dụng nó kết hợp với một Listtrong các giới hạn của bạn.

List<int> bounds = new List<int>() {int.MinValue, 0, 4, 9, 17, 20, int.MaxValue };

switch (bounds.IndexOf(bounds.Last(x => x < j)))
{
    case 0: // <=0
        break;

    case 1: // >= 1 and <=4
        break;
    case 2: // >= 5 and <=9
        break;
    case 3: // >= 10 and <=17
        break;
    case 4: // >= 18 and <=20
        break;

    case 5: // >20
        break;
}

Với cách tiếp cận này, phạm vi có thể có các nhịp khác nhau.


6

Khoảng thời gian là không đổi:

 int range = 5
 int newNumber = number / range;
 switch (newNumber)
 {
      case (0): //number 0 to 4
                break;
      case (1): //number 5 to 9
                break;
      case (2): //number 10 to 14
                break;
      default:  break;
 }

Nếu không thì:

  if else

3

Như đã đề cập if-elsesẽ tốt hơn trong trường hợp này, nơi bạn sẽ xử lý một phạm vi:

if(number >= 1 && number <= 4)
{
   //do something;
}
else if(number >= 5 && number <= 9)
{
   //do something else;
}

2

Trong .Net chỉ Visual Basic cho phép phạm vi trong câu lệnh chuyển đổi, nhưng trong C # không có cú pháp hợp lệ cho điều này.

Giải quyết vấn đề cụ thể của bạn trong C #, tôi sẽ giải quyết nó như vậy:

if(number >= 1 && number <= 9) // Guard statement
{
    if(number < 5)
    {
        // Case (1 to 4):

        //break;

    }
    else
    {
        // Case (5 to 9):

        //break;

    }

}
else
{
    // Default code goes here

    //break;

}

Để minh họa thêm điều này, hãy tưởng tượng bạn có một giá trị phần trăm.

Sử dụng vấn đề của bạn làm mẫu, bạn có thể muốn điều này giống như sau:

switch (percentage)
{
    case (0 to 19):
        break;

    case (20 to 39):
        break;

    case (40 to 69):
        break;

    case (70 to 79):
        break;

    case (80 to 100):
        break;

    default:
        break;

}

Tuy nhiên, vì C # không cho phép cú pháp đó, đây là một giải pháp mà C # cho phép:

if (percentage >= 0 && percentage <= 100) // Guard statement
{
    if (percentage >= 40)
    {
        if (percentage >= 80)
        {
            // Case (80% to 100%)

            //break;

        }
        else
        {
            if (percentage >= 70)
            {
                // Case (70% to 79%)

                //break;

            }
            else
            {
                // Case (40% to 69%)

                //break;

            }

        }

    }
    else
    {
        if (percentage >= 20)
        {
            // Case (20% to 39%)

            //break;

        }
        else
        {
            // Case (0% to 19%)

            //break;

        }

    }

}
else
{
    // Default code goes here

    //break;

}

Có thể mất một chút thời gian để làm quen, nhưng sẽ ổn khi bạn đã hiểu.

Cá nhân tôi hoan nghênh các tuyên bố chuyển đổi để cho phép phạm vi.

Tương lai của câu lệnh switch C #

Dưới đây là một số ý tưởng tôi có về cách cải thiện các câu lệnh switch:

Phiên bản A

switch(value)
{
    case (x => x >= 1 && x <= 4):
    break;

    case (x => x >= 5 && x <= 9):
    break;

    default:
    break;

}

Phiên bản B

switch(param1, param2, ...)
{
    case (param1 >= 1 && param1 <= 4):
    break;

    case (param1 >= 5 && param1 <= 9 || param2 != param1):
    break;

    default:
    break;

}

1

Nếu bạn sử dụng C / C ++, không có cú pháp "phạm vi". Bạn chỉ có thể liệt kê tất cả các giá trị sau mỗi phân đoạn "trường hợp". Cú pháp phạm vi hỗ trợ ngôn ngữ Ada hoặc Pascal.


0

Trước hết, bạn nên chỉ định ngôn ngữ lập trình mà bạn đang đề cập đến. Thứ hai, các switchcâu lệnh được sử dụng thích hợp cho các tập hợp tùy chọn đóng liên quan đến biến được chuyển mạch, ví dụ như liệt kê hoặc chuỗi được xác định trước. Đối với trường hợp này, tôi khuyên bạn nên sử dụng if-elsecấu trúc cũ tốt .


0

Qua switchtrường hợp nó là impossible.You có thể đi với lồng nhau nếu phát biểu.

if(number>=1 && number<=4){
//Do something
}else if(number>=5 && number<=9){
//Do something
}

Còn tốt cũ (number >= 1 && number <= 4)thay vì kiểm tra từng con số? Bạn sẽ viết như thế nào từ 1 đến 120 ? ;-)
DarkDust

Oh, và chú ý đến =vs ==.
DarkDust

-1

Nếu câu hỏi là về C (bạn không nói), thì câu trả lời là không, nhưng : GCC và Clang (có thể những người khác) hỗ trợ cú pháp phạm vi , nhưng nó không hợp lệ ISO C:

switch (number) {
    case 1 ... 4:
        // Do something.
        break;

    case 5 ... 9:
        // Do something else.
        break;
}

Đảm bảo có khoảng trắng trước và sau dấu ...nếu không bạn sẽ gặp lỗi cú pháp.


Pascal / delphi cũng làm được điều này. case number of 1..4: làm gì đó; vv
Kell

Câu hỏi đặt ra là về C #
SuB

@SuB: Tôi biết. Tôi đã thêm thẻ C # vào câu hỏi này sau khi OP cuối cùng đã cho chúng tôi biết câu hỏi nói về ngôn ngữ nào. Nhưng câu trả lời vẫn có thể hữu ích cho những người đến đây qua công cụ tìm kiếm, đó là lý do tại sao tôi chưa xóa nó.
DarkDust

-1

Trong C #, các trường hợp chuyển đổi về cơ bản là từ điển về những việc cần làm tiếp theo. Vì bạn không thể tra cứu một phạm vi trong từ điển, điều tốt nhất bạn có thể làm là ... trường hợp mà Steve Gomez đề cập.


-3

Bạn có thể sử dụng câu lệnh if-else với || toán tử (hoặc toán tử) như:

if(case1 == true || case2 == true || case3 == true)
   {
    Do this!... 
   }
else if(case4 == true || case5 == true || case6 == true)
   {
    Do this!... 
   }
else if(case7 == true || case8 == true || case9 == true)
   {
    Do this!... 
   }

Chà, điều đó hơi phức tạp đối với những thứ như thế if (number >= 1 && number <= 4) { … } else if (number >= 5 && number <= 9) { … }, bạn có nghĩ vậy không?
DarkDust

Ồ được rồi ... Ehm nhưng nếu các trường hợp được cho là làm điều tương tự không được sắp xếp, bạn cần phải sử dụng '|| nhà điều hành '...
Lukas Warsitz

Nhưng quan điểm của anh ấy là kiểm tra xem một số có nằm trong một phạm vi hay không, vì vậy thứ tự không quan trọng (ngoại trừ các phạm vi đã được kiểm tra).
DarkDust

Nó không phải là một lỗi , giải pháp của bạn là không sai, chỉ phức tạp ;-)
DarkDust

== true: face_palm: đây là hành vi mặc định và đối với == false, bạn có thể sử dụng toán tử not
Et7f3XIV
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.