如何在编程语言中编写“x == 1或2”?

时间:2010-10-06 06:35:09

标签: language-design boolean-operations

  

可能重复:
  Why do most programming languages only have binary equality comparison operators?

自从我开始学习编程语言以来,我有一个很长时间的简单问题。

如果x为1或2 => TRUE(否则为FALSE),我想像那样写。“

但是当我用编程语言编写它时,比如C,

( x == 1 || x == 2 )

它确实有效,但看起来很尴尬,难以阅读。我想应该可以简化这样的或操作,所以如果您有任何想法,请告诉我。谢谢,Nathan

22 个答案:

答案 0 :(得分:36)

Python允许测试序列中的成员资格:

if x in (1, 2):

答案 1 :(得分:18)

C#中的扩展程序

第1步:创建扩展方法

public static class ObjectExtensions
{
    public static bool Either(this object value, params object[] array)
    {
        return array.Any(p => Equals(value, p));
    }
}

第2步:使用扩展方法

if (x.Either(1,2,3,4,5,6)) 
{
}
else
{
}

答案 2 :(得分:17)

虽然在这个帖子中有很多非常有趣的答案,但我想指出,如果你根据语言在循环中做这种逻辑,它们可能会有性能影响。就计算机而言,if (x == 1 || x == 2)是编译成机器代码时最容易理解和优化的。{/ p>

答案 3 :(得分:11)

当我开始编程时,对我来说似乎很奇怪,而不是像:

(1 < x < 10)

我不得不写:

(1 < x && x < 10)

但这就是大多数编程语言的工作方式,过了一段时间你就会习惯它。

所以我认为写

是完全可以的
( x == 1 || x == 2 )

以这种方式编写也具有其他程序员可以轻松理解您所写内容的优势。使用函数来封装它可能会使事情变得更复杂,因为其他程序员需要找到该函数并查看它的作用。

只有像Python,Ruby等更新的编程语言允许您以更简单,更好的方式编写它。这主要是因为这些编程语言旨在提高程序员的工作效率,而较旧的编程语言的主要目标是应用程序性能,而不是程序员的工作效率。

答案 4 :(得分:9)

这是自然的,但依赖于语言

您的方法确实看起来更自然,但这实际上取决于您用于实施的语言。

混乱的基本原理

Csystems programming language,并且非常接近硬件(虽然很滑稽,因为我们过去常常考虑使用“高级”语言,而不是编写机器代码),但这并不完全正确expressive

Modern higher-level languages(同样,有争议的是,lisp并不是现代的,从历史上来说,但是可以让你做得很好)允许你通过使用内置的构造或库支持来做这些事情(例如,使用范围,元组或等同语言,如PythonRubyGroovyML-languagesHaskell ...)。

可能的解决方案

选项1

您可以选择实现function or subroutine获取一系列值并进行检查。

这是一个基本原型,我将实施作为练习留给你:

/* returns non-zero value if check is in values */
int is_in(int check, int *values, int size);

但是,正如您将很快看到的,这是非常基本的,而且不够灵活:

  • 仅适用于整数,
  • 仅用于比较相同的值。

选项2

复杂性阶梯(在语言方面)更高一步,另一种方法是在pre-processor(或macros)中使用C C++来实现类似的行为,但要注意side effects

其他选项

下一步可能是传递function pointer作为额外参数来定义调用点的行为,为此定义几个变体和别名,并自己构建一个小型的比较器库。

接下来的步骤是在C++中使用templates在单个实现的不同类型上实现类似的操作。

然后继续从那里到higher-level languages


选择正确的语言(或学会放手!)

通常情况下,由于显而易见的原因,支持functional programming的语言会对此类内容提供内置支持。

或者只是学习接受某些语言可以做其他人不能的事情,并且取决于工作和环境,这就是它的方式。它主要是语法糖,你可以做的并不多。此外,有些语言会通过更新其规格来解决它们的缺点,而其他语言则会停滞不前。

也许图书馆已经实现了这样的事情而且我不知道。

答案 5 :(得分:7)

这是很多有趣的选择。我很惊讶没人提到开关......案例 - 所以这里是:

switch(x) {
case 1:
case 2:
  // do your work
  break;
default:
  // the else part
}
  1. 它比拥有一个更具可读性 一堆x == 1 || x == 2 || ...
  2. 比拥有更优秀 用于执行a的数组/设置/列表 会员资格检查

答案 6 :(得分:6)

呃,这有什么问题?哦,好吧,如果你真的使用它很多而讨厌看起来在c#中做这样的事情:

#region minimizethisandneveropen
public bool either(value,x,y){       
    return (value == x || value == y);
}
#endregion

并在您使用它的地方:

if(either(value,1,2))
   //yaddayadda 

或者其他语言的东西:)。

答案 7 :(得分:6)

我怀疑我是否会这样做,但回答你的问题,这是在C#中实现它的一种方法,涉及一些通用类型推断和一些滥用运算符重载。您可以编写如下代码:

if (x == Any.Of(1, 2)) {
    Console.WriteLine("In the set.");
}

Any类定义为:

public static class Any {
    public static Any2<T> Of<T>(T item1, T item2) {
        return new Any2<T>(item1, item2);
    }
    public struct Any2<T> {
        T item1;
        T item2;
        public Any2(T item1, T item2) {
            this.item1 = item1;
            this.item2 = item2;
        }
        public static bool operator ==(T item, Any2<T> set) {
            return item.Equals(set.item1) || item.Equals(set.item2);
        }
        // Defining the operator== requires these three methods to be defined as well:
        public static bool operator !=(T item, Any2<T> set) {
            return !(item == set);
        }
        public override bool Equals(object obj) { throw new NotImplementedException(); }
        public override int GetHashCode() { throw new NotImplementedException(); }
    }
}

你可以想象Any.Of方法有许多重载来处理3个,4个甚至更多的参数。也可以提供其他运算符,并且伴随All类可以执行非常类似的操作,但使用&&代替||

看看反汇编,由于需要调用Equals,所以会发生相当多的装箱,因此最终会比明显的(x == 1) || (x == 2)构造慢。但是,如果您将所有<T>更改为int并将Equals替换为==,则会得到一些内容似乎很好地内联到与(x == 1) || (x == 2)

答案 8 :(得分:3)

在php中你可以使用

$ret = in_array($x, array(1, 2));

答案 9 :(得分:3)

据我所知,在C中没有内置的方法。你可以添加自己的内联函数来扫描一个int数组,其值等于x ....

像这样:

inline int contains(int[] set, int n, int x)
{ 
  int i;
  for(i=0; i<n; i++)
    if(set[i] == x)
      return 1;

  return 0;
}

// To implement the check, you declare the set
int mySet[2] = {1,2};
// And evaluate like this:
contains(mySet,2,x) // returns non-zero if 'x' is contained in 'mySet'

答案 10 :(得分:3)

在COBOL中(自从我对COBOL进行了简短的浏览已经有很长一段时间了,所以我在这里可能会有一两个错误):

IF X EQUALS 1 OR 2
...

所以语法肯定是可能的。然后问题归结为“为什么不经常使用它?”

嗯,问题是,解析这样的表达式有点像婊子。不是那样单独站立时,请注意,但在复合表达时更多。语法开始变得不透明(从编译器实现者的角度来看)和语义彻头彻尾的毛茸茸。 IIRC,许多COBOL编译器甚至会警告你,如果你因为潜在的问题而使用这样的语法。

答案 11 :(得分:3)

在.Net中你可以使用Linq:

int[] wanted = new int{1, 2};

// you can use Any to return true for the first item in the list that passes
bool result = wanted.Any( i => i == x );

// or use Contains
bool result = wanted.Contains( x );

虽然我个人觉得基本的||很简单:

bool result = ( x == 1 || x == 2 );

答案 12 :(得分:3)

在T-SQL中

where x in (1,2)

答案 13 :(得分:2)

谢谢伊格纳西奥!我把它翻译成Ruby:

[ 1, 2 ].include?( x )

它也有效,但我不确定它是否看起来很清楚&amp;正常。如果你了解Ruby,请告知。如果有人知道如何在C中写这个,请告诉我。谢谢。 -Nathan

答案 14 :(得分:2)

Pascal有一个(有限的)集合概念,所以你可以这样做:

if x in [1, 2] then

(几十年来没有触及Pascal编译器,因此语法可能已关闭)

答案 15 :(得分:2)

Perl 5与Perl6::Junction

use Perl6::Junction 'any';
say 'yes' if 2 == any(qw/1 2 3/);

Perl 6:

say 'yes' if 2 == 1|2|3;

这个版本是如此易读和简洁我将使用它而不是||运算符。

答案 16 :(得分:1)

你说符号(x==1 || x==2)是“笨拙且难以阅读”。我不敢苟同。它与自然语言不同,但非常清晰易懂。你只需要像电脑一样思考。

此外,此帖子中提到的符号x in (1,2)在语义上与您真正要求的不同,他们会询问x是否是 {{1}的成员这不是你要问的。您 提出的问题是(1,2),它在逻辑上(和语义上)等同于if x equals to 1 or to 2,转换为if x equals to 1 or x equals to 2

答案 17 :(得分:1)

只有一个非按位布尔运算符的尝试(不建议,未经测试):

if( (x&3) ^ x ^ ((x>>1)&1) ^ (x&1) ^ 1 == 0 )

(x&3) ^ x部分应该等于0,这可以确保x在0到3之间。其他操作数只能设置最后一位。

((x>>1)&1) ^ (x&1) ^ 1部分确保最后一位和倒数第二位不同。这适用于1和2,但不适用于0和3。

答案 18 :(得分:1)

在java中:

 List list = Arrays.asList(new Integer[]{1,2});
 Set set = new HashSet(list);
 set.contains(1)

答案 19 :(得分:0)

我有一个宏,我使用了很多你想要的东西。

#define ISBETWEEN(Var, Low, High) ((Var) >= (Low) && (Var) <= (High))

如果x为1或2,

ISBETWEEN(x, 1, 2)将返回true。

答案 20 :(得分:0)

C,C ++,VB.net,C#.net以及我所知道的任何其他语言都没有一种有效的方法来测试某些选择之一。虽然(x == 1 || x == 2)通常是编码这种结构的最自然的方法,但这种方法有时需要创建一个额外的临时变量:

  tempvar = somefunction(); // tempvar only needed for 'if' test:
  if (tempvar == 1 || tempvar == 2)
    ...

当然,优化器应该能够有效地摆脱临时变量(在它使用的短暂时间内将其推入寄存器)但我仍然认为代码很难看。此外,在某些嵌入式处理器上,最紧凑且可能最快的写入方式(x == const1 || x == const2 || x == const3)是:

  movf  _x,w             ; Load variable X into accumulator
  xorlw const1           ; XOR with const1
  btfss STATUS,ZERO      ; Skip next instruction if zero
   xorlw const1 ^ const2 ; XOR with (const1 ^ const2)
  btfss STATUS,ZERO      ; Skip next instruction if zero
   xorlw const2 ^ const3 ; XOR with (const2 ^ const3)
  btfss STATUS,ZERO      ; Skip next instruction if zero
   goto NOPE

这种方法需要为每个常量添加两条指令;所有指令都将执行。如果分支被采用,提前退出测试将节省时间,否则将浪费时间。使用单独比较的字面解释进行编码将需要针对每个常量的四条指令。

如果一种语言的“if变量是几个常量之一”构造,我希望编译器使用上面的代码模式。太糟糕了,没有这种结构存在于通用语言中。

(注意:Pascal确实有这样的构造,但运行时实现通常非常浪费时间和代码空间。)

答案 21 :(得分:-2)

返回x === 1 || x === 2在javascript中