有没有办法让 Objective-C 支持多变量 switch 结构?

发布于 2024-11-14 19:03:28 字数 757 浏览 0 评论 0原文

我想知道:有没有办法让 Objective-C 支持多变量 switch 结构?

我的意思是,很多时候我必须处理解决方案取决于一对变量而不是单个变量的问题。对于一长串单变量值,可以使用简单的 switch/case 构造:

switch (var) {
    case 0: ...
    case 1: ...
    default: ...
}

但是当您必须处理两个值的组合时,您经常会碰巧做这样的事情:

switch (var1) {
    case 0: 
        switch (var2) {
            case 0: ...
            case 1: ...
        }
    case 1: 
        switch (var2) {
            case 0: ...
            case 1: ...
        }        
    ...
}

而且它会变得更多并且更复杂......我真正想做的是这样的事情:

switch (var1, var2) {
    case (0,0) : ...
    case (1,0) : ...
    case (*,1) : ...
    default: ...
}

这将导致更简单和可读的构造。有什么解决方案可以支持这样的结构吗?或者这个的一个细微的变化?

I was wondering: is there a way to make Objective-C support a multi-variable switch construct?

I mean, very often I have to deal with problems in which the solution depends on a pair of variables instead of a single one. For a long list of single variable values one can use a simple switch/case construct:

switch (var) {
    case 0: ...
    case 1: ...
    default: ...
}

But when you have to deal with the combination of two values you often happen to do something like this:

switch (var1) {
    case 0: 
        switch (var2) {
            case 0: ...
            case 1: ...
        }
    case 1: 
        switch (var2) {
            case 0: ...
            case 1: ...
        }        
    ...
}

And it gets more and more complicated ... What I'd really love to do is something like this:

switch (var1, var2) {
    case (0,0) : ...
    case (1,0) : ...
    case (*,1) : ...
    default: ...
}

that will result in a more simple and readable construct. Is there any solution to support such a structure? Or a slight variation of this one?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

橘味果▽酱 2024-11-21 19:03:28

我喜欢 saphrosit 的答案,但我会尽力使其易于理解。

将问题的可能结果想象为网格中的方块,其中网格边缘的一条边代表 var1 的值,另一条边代表 var2 的可能值,那么如果您递增地计算网格的方块,则它会得到像这样的东西吗?

      ||                              var1                                   |    
      ||    0    |     1     |     2     | ... |     j     | ... |   n-1     |
======++=====================================================================|
    0 ||    0    |     1     |     2     | ... |     j     | ... |   n-1     |
   ---||---------+-----------+-----------+-----+-----------+-----+-----------|
    1 ||    n    |    n+1    |    n+2    | ... |    n+j    | ... |  n+(n-1)  |
   ---||---------+-----------+-----------+-----+-----------+-----+-----------| 
    2 ||   2*n   |   2*n+1   |  2*n+2    | ... |   2*n+j   | ... | 2*n+(n-1) |
 v ---||---------+-----------+-----------+-----+-----------+-----+-----------|
 a    ||    .    |     .     |     .     |     |     .     |     |  .        |
 r ---||---------+-----------+-----------+-----+-----------+-----+-----------|
 2  i ||   i*n   |   i*n+1   |   i*n+2   | ... |   i*n+j   | ... | i*n+(n-1) |
   ---||---------+-----------+-----------+-----+-----------+-----+-----------|
      ||    .    |      .    |      .    |     |     .     |     |  .        |
  ----||---------+-----------+-----------+-----+-----------+-----+-----------|
  m-1 || (m-1)*n | (m-1)*n+1 | (m-1)*n+2 | ... | (m-1)*n+j | ... |   mn-1    | <-- (m-1)*n+(n-1) = m*n-n + (n-1) = mn-1
------||---------+-----------+-----------+-----+-----------+-----+-----------|

这将被称为行主矩阵,因为您从跨行计数开始。还有一个列主矩阵,您首先开始倒数而不是横向倒数。这就是矩阵在 C BLAS 库中的存储方式,因此对于很多人来说应该非常相似。

在您的情况下,您正在寻找的结果可以解决为 var3 = var2*n + var1 您可以将其放在代码中,如下

#define N 10 // Maximum size of var1

int main() {

   int var1 = 1;
   int var2 = 1;

   switch(var1 + var2 * N){
      case 1 + 1 * N: printf("One One"); break;
      case 2 + 2 * N: printf("Two Two"); break;
      default:
      printf("Bada Bing");
   }

   return 0;
}

所示:注意:之前的代码不起作用,这有效。

I like the answer from saphrosit but I'll make try to make it easy to understand.

Imagine the possible outcomes of your problem as squares in a grid where one edge of the edge of the grid represents values of var1 and the other edge represents the possible values of var2, then if you incrementialy counted through the squares of the of the grid you would it get something like this

      ||                              var1                                   |    
      ||    0    |     1     |     2     | ... |     j     | ... |   n-1     |
======++=====================================================================|
    0 ||    0    |     1     |     2     | ... |     j     | ... |   n-1     |
   ---||---------+-----------+-----------+-----+-----------+-----+-----------|
    1 ||    n    |    n+1    |    n+2    | ... |    n+j    | ... |  n+(n-1)  |
   ---||---------+-----------+-----------+-----+-----------+-----+-----------| 
    2 ||   2*n   |   2*n+1   |  2*n+2    | ... |   2*n+j   | ... | 2*n+(n-1) |
 v ---||---------+-----------+-----------+-----+-----------+-----+-----------|
 a    ||    .    |     .     |     .     |     |     .     |     |  .        |
 r ---||---------+-----------+-----------+-----+-----------+-----+-----------|
 2  i ||   i*n   |   i*n+1   |   i*n+2   | ... |   i*n+j   | ... | i*n+(n-1) |
   ---||---------+-----------+-----------+-----+-----------+-----+-----------|
      ||    .    |      .    |      .    |     |     .     |     |  .        |
  ----||---------+-----------+-----------+-----+-----------+-----+-----------|
  m-1 || (m-1)*n | (m-1)*n+1 | (m-1)*n+2 | ... | (m-1)*n+j | ... |   mn-1    | <-- (m-1)*n+(n-1) = m*n-n + (n-1) = mn-1
------||---------+-----------+-----------+-----+-----------+-----+-----------|

This would is called a row major matrix since you start by counting accross the rows. There is also a column major matrix where you start counting down first instead of across. This is how matrixes are stored in the C BLAS library so it should be very fimilar to many people.

In your case the outcome you're looking for can be addressed as var3 = var2*n + var1 you could lay this out in code as

#define N 10 // Maximum size of var1

int main() {

   int var1 = 1;
   int var2 = 1;

   switch(var1 + var2 * N){
      case 1 + 1 * N: printf("One One"); break;
      case 2 + 2 * N: printf("Two Two"); break;
      default:
      printf("Bada Bing");
   }

   return 0;
}

NOTE: the code that was here earlier wouldn't have worked, this works.

假装爱人 2024-11-21 19:03:28

在你的问题中你提到:
“我真正想做的是这样的:”

switch (var1, var2) {
    case (0,0) : ...
    case (1,0) : ...
    case (*,1) : ...
    default: ...
}

如果您的可能值在 {0..n} 范围内,则可以使用两种方法。

  1. 你可以构造一个
    选择器的多维数组
    然后选择正确的选择器
    使用您的 var1、var2。 (由于在编译时构造选择器,因此该方法更有效)

  2. 您可以构造选择器
    基于的值的名称
    var,var2 变量。

此代码片段中举例说明了这两种方法。

- (void) case00 {
    NSLog(@"Case ZeroZero");
}

- (void) testSelectorIdea {
     NSInteger var1 = 0;
     NSInteger var2 = 0;

// ----- ARRAY OF SELECTORS METHOD ----
    SEL selectors[2][2] = {@selector(case00),@selector(case01), @selector(case10), @selector(case11)};
    [self performSelector:selectors[var1][var2]];


// ----- SELECTOR CONSTRUCTION METHOD ----
    NSString * selectorName = [NSString stringWithFormat:@"case%d%d",var1,var2];
    SEL  selector = NSSelectorFromString(selectorName);
    [self  performSelector:selector];

}

In your question you mention:
"What I'd really love to do is something like this:"

switch (var1, var2) {
    case (0,0) : ...
    case (1,0) : ...
    case (*,1) : ...
    default: ...
}

If it is the case that your possible values are in the range {0..n}, there are two methods you could use.

  1. You could construct a
    multidimensional array of selectors
    and then select the correct selector
    using your var1, var2. (This method is more efficient due to the constructing of the selectors at compile time)

  2. You could construct the selector
    name based on the values of the
    var,var2 variables.

BOTH methods are exemplified here in this code snippet.

- (void) case00 {
    NSLog(@"Case ZeroZero");
}

- (void) testSelectorIdea {
     NSInteger var1 = 0;
     NSInteger var2 = 0;

// ----- ARRAY OF SELECTORS METHOD ----
    SEL selectors[2][2] = {@selector(case00),@selector(case01), @selector(case10), @selector(case11)};
    [self performSelector:selectors[var1][var2]];


// ----- SELECTOR CONSTRUCTION METHOD ----
    NSString * selectorName = [NSString stringWithFormat:@"case%d%d",var1,var2];
    SEL  selector = NSSelectorFromString(selectorName);
    [self  performSelector:selector];

}
一直在等你来 2024-11-21 19:03:28

正如其他人所说,如果您发现自己想要这样做,那么您应该真正考虑一种更好地构建数据的方法。您似乎正在处理标量类型。我倾向于发现一点 C++ 的作用很大,您可以使用 Objective-C++ 将其集成到 Objective-C 项目中。也就是说,如果你确定你想要你所说的你想要的,并且你不反对预处理器的邪恶,你可以尝试这样的事情:

#define BEGIN_SWITCH(type,...) ({  typedef type T; T switchVars[] = { __VA_ARGS__ }; BOOL performAction;

#define CASE(...) { \
            T caseVars[] = { __VA_ARGS__ }; \
            performAction = YES; \
            size_t count = MIN(sizeof(switchVars), sizeof(caseVars)) / sizeof(T); \
            for (size_t i = 0 ; i < count / sizeof(T) ; i++) \
            { \
                if (caseVars[i] != switchVars[i]) \
                { \
                    performAction = NO; \
                    break; \
                } \
            } \
        } \
        if (performAction)

#define END_SWITCH });

int main (int argc, char const *argv[])
{
    id pool = [[NSAutoreleasePool alloc] init];

    int a1 = 0;
    int a2 = 5;
    int a3 = 10;

    BEGIN_SWITCH(int, a1, a2, a3)
        CASE(0,5) NSLog(@"0,5");
        CASE(1,2,3) NSLog(@"1,2,3");
        CASE(0,5,10) NSLog(@"0,5,10");
        CASE(1) NSLog(@"1");
    END_SWITCH

    [pool drain];

    return 0;
}

它不太像 switch/case,因为你不能堆叠多重情况:子句相互叠加。在任何情况下,您都必须添加默认值并以某种方式中断 - 也许您可以使用一些额外的宏和跳转到中断来完成此操作。关于预处理器的标准警告适用:它不像 Objective-C 那样漂亮,并且很容易给你带来各种深不可测的语法错误。但如果你真的想要改变语言的语法,那么你的选择要么是这样,要么是在苹果公司工作。

As others have said, if you find yourself wanting to do this, then you should really think about a way of structuring your data better. You seem like you're dealing with scalar types. I tend to find a little c++ goes a long way there, and you can integrate that into an objective-c project using objective-c++. That said, if you're sure you want what you say you want and you're not averse to evilness with the preprocessor, you could try something like this:

#define BEGIN_SWITCH(type,...) ({  typedef type T; T switchVars[] = { __VA_ARGS__ }; BOOL performAction;

#define CASE(...) { \
            T caseVars[] = { __VA_ARGS__ }; \
            performAction = YES; \
            size_t count = MIN(sizeof(switchVars), sizeof(caseVars)) / sizeof(T); \
            for (size_t i = 0 ; i < count / sizeof(T) ; i++) \
            { \
                if (caseVars[i] != switchVars[i]) \
                { \
                    performAction = NO; \
                    break; \
                } \
            } \
        } \
        if (performAction)

#define END_SWITCH });

int main (int argc, char const *argv[])
{
    id pool = [[NSAutoreleasePool alloc] init];

    int a1 = 0;
    int a2 = 5;
    int a3 = 10;

    BEGIN_SWITCH(int, a1, a2, a3)
        CASE(0,5) NSLog(@"0,5");
        CASE(1,2,3) NSLog(@"1,2,3");
        CASE(0,5,10) NSLog(@"0,5,10");
        CASE(1) NSLog(@"1");
    END_SWITCH

    [pool drain];

    return 0;
}

It isn't quite like switch/case, as you can't stack multiple case: clauses on top of oneanother. You'd have to add in default and break somehow in any case -- maybe you could do this with some extra macros and a goto for break. Standard caveats about the prepreocessor apply: It isn't pretty as Objective-C, and will be prone to giving you all kinds of unfathomable syntax errors. But if you really want to alter the syntax of the language, then your options are either something like this or getting a job with Apple.

南笙 2024-11-21 19:03:28

不是解决方案,只是一种解决方法:您可能会想到这样的事情,

SInt32 var1, var2;
/*...*/
SInt64 var3 = var1<<32 + var2;

switch(var3) {
 .
 .
 .
}

如果您的变量具有某些特定的属性,您可以使用它来进行一些轻微的简化,即如果变量 < 10 那么你可以使用

 var3 = 10*var1+var2;

Not a solution, just a workaround: you may think to something like this

SInt32 var1, var2;
/*...*/
SInt64 var3 = var1<<32 + var2;

switch(var3) {
 .
 .
 .
}

if your vars have some particular property you may use it to do some slight simplifications, i.e. if vars are < 10 then you may use

 var3 = 10*var1+var2;
似最初 2024-11-21 19:03:28

您确定这是具有此类结构的良好编程风格吗:)?
Switch 语句旨在加速多个 if () else if () 语句,但是当您需要比较多个变量时,优化就会进行。

一种方法是使用逻辑移位/其他操作将多个变量放入一个变量中,另一种方法是使用 if ((a == 0) & (b == 0)) {...} else if (( a == 0) && (b == 1))...
那不会占用太多空间。

Are you sure that this is a good programming style to have such constructions :) ?
Switch statement is designed to speedup multiple if () else if () statements, but when you will need to compare multiple variables that optimization will go.

The one way is to use logical shifts/other operations to place multiple variables in one, and the other is to use if ((a == 0) & (b == 0)) {...} else if ((a == 0) && (b == 1))....
That wouldn't take a lot of space.

情仇皆在手 2024-11-21 19:03:28

由于 ObjC-Runtime 的存在,应该可以使用选择器类型 SEL/@selector()/performSelector, NSSelectorFromString、NSArrays/NSDictionaries 和 NSIndexPathes,这比 c-switch 语句更强大。
但它不会驻留在语言级别,因为这个 Python 代码 也不是这样。

Due to the existences of the ObjC-Runtime, it should be possible to build up a switch replacement with things like the selector type SEL/@selector()/performSelector, NSSelectorFromString, NSArrays/NSDictionaries and NSIndexPathes, that is way more powerful than the c-switch statement.
But it won't reside on language level, as this Python-code isn't as-well.

旧伤慢歌 2024-11-21 19:03:28

怎么样:

switch ([NSString StringWithFormat: @"%d,%d", var1, var2]) {
    case (@"0,0") : ...
    case (@"1,0") : ...
    case (@"*,1") : ...
    default: ...
}

问题是 *,1 但你可以把它们全部拼写出来,或者你可以做一个 contains @",1" (我忘记了正确的语法 atm)

How about something like:

switch ([NSString StringWithFormat: @"%d,%d", var1, var2]) {
    case (@"0,0") : ...
    case (@"1,0") : ...
    case (@"*,1") : ...
    default: ...
}

The problem would be *,1 but you could either spell those all out, or you could do a contains @",1" (I forget the right syntax atm)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文