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

Cul*_*lip 25 language-design boolean-operations

可能重复:
为什么大多数编程语言只有二进制相等比较运算符?

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

我想写"如果x是1或2 => TRUE(否则为FALSE)."

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

( x == 1 || x == 2 )
Run Code Online (Sandbox Code Playgroud)

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

Ign*_*ams 36

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

if x in (1, 2):
Run Code Online (Sandbox Code Playgroud)

  • 那不是一个数组,它是一个叫做**元组**的结构.使用一个最多5个左右的值是正常的; 除此之外,使用**集**更有效(序列中的包含测试是O(n),而集合中的包含测试是O(1)). (17认同)
  • 但不会创建该集是O(n)? (7认同)
  • @progo:因为集合表示为哈希表,它具有恒定的平均查找时间. (2认同)
  • Pascal中的语法相同,另外,您可以使用set(1,2,3)或间隔(1..3).对于我来说,在使用Pascal(切换/案例的力量)与Pas/Case之后学习它时,这是C的主要失误之一,它在Pascal中允许以集合和间隔进行测试. (2认同)

And*_*ngs 18

C#中的扩展版本

第1步:创建扩展方法

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

第2步:使用扩展方法

if (x.Either(1,2,3,4,5,6)) 
{
}
else
{
}
Run Code Online (Sandbox Code Playgroud)

  • @Piers Myers只需使用`(Array.IndexOf(values,value)> -1)`所以你不必创建一个新列表. (2认同)

Dar*_*oid 17

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

  • @intuited - 仅供参考:在Python 3.1.2中,两者的性能几乎相同.我只是'时间'它,如果`x`是1,我在`in`得到0.042秒,对于'或`得到0.047秒,如果`x`是2或0,我得到0.08秒.所以如果你是在Python中进行微优化,查看您正在测试的条件的顺序...... (3认同)
  • 但这取决于语言.我希望Python为`x in(1,2)`生成的代码至少与Python为`x == 1或x == 2'生成的代码一样优化.当然在C中,相反的是真正. (2认同)

Flo*_*rin 11

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

(1 < x < 10)
Run Code Online (Sandbox Code Playgroud)

我不得不写:

(1 < x && x < 10)
Run Code Online (Sandbox Code Playgroud)

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

所以我相信写作完全没问题

( x == 1 || x == 2 )
Run Code Online (Sandbox Code Playgroud)

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

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

  • 你可以用Python做第一个例子! (4认同)

hay*_*lem 9

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

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

混乱的基本原理

C是一种系统编程语言,并且非常接近硬件(虽然很滑稽,因为我们曾经考虑过"高级"语言,而不是编写机器代码),但它并不完全具有表现力.

现代高级语言(再次,可论证,lisp并不是现代的,从历史上讲,但是可以让你做得很好)允许你通过使用内置的构造或库支持来做这些事情(例如,使用Ranges,Python,Ruby,Groovy,ML-languages,Haskell等语言中的元组或等价物.

可能的解决方案

选项1

您可以选择实现一个函数或子例程来获取值数组并检查它们.

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

/* returns non-zero value if check is in values */
int is_in(int check, int *values, int size);
Run Code Online (Sandbox Code Playgroud)

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

  • 它只适用于整数,
  • 它仅用于比较相同的值.

选项2

一个步骤的复杂性梯子(在语言方面)更高,可选的是使用预处理器 Ç(或C++),以实现类似的行为,但要小心副作用.

其他选择

下一步可以是将函数指针作为额外参数传递,以定义调用点处的行为,为此定义几个变体和别名,并构建一个小型的比较器库.

接下来的步骤是使用模板C++中实现类似的东西,使用单个实现在不同类型上执行此操作.

然后继续从那里到更高级别的语言.


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

通常,出于显而易见的原因,有利于函数式编程的语言将内置支持此类事物.

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

也许一个图书馆已经实现了这样的事情,我不知道.


kar*_*eek 7

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

switch(x) {
case 1:
case 2:
  // do your work
  break;
default:
  // the else part
}
Run Code Online (Sandbox Code Playgroud)
  1. 它比一堆x == 1 ||更具可读性 x == 2 || ...
  2. 比使用数组/集/列表进行成员资格检查更为理想

  • 我不同意它看起来更具可读性.x == 1 || 与我认为的开关相比,x == 2非常简单.它可能比数组检查更优化,但它可能不比原始语句更优化. (2认同)
  • 当你进行两次比较时可能不那么明显,但是当你说10次比较然后做ax == 1 ||时 ... x == 10也会变得势不可挡并且容易出错.虽然你比较相同的var"x",你重复它10次 - 你需要通过所有10个htem来确保它们中的一个不是"y" (2认同)

bas*_*ijn 6

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

#region minimizethisandneveropen
public bool either(value,x,y){       
    return (value == x || value == y);
}
#endregion
Run Code Online (Sandbox Code Playgroud)

在您使用它的地方:

if(either(value,1,2))
   //yaddayadda 
Run Code Online (Sandbox Code Playgroud)

或者类似于另一种语言的东西:).

  • 你可以避免函数中的条件:`return(value == x || value == y);` (3认同)

Wes*_*ill 6

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

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

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(); }
    }
}
Run Code Online (Sandbox Code Playgroud)

你可以想象有多个Any.Of方法的重载来处理3,4或甚至更多的参数.也可以提供其他操作员,并且伴侣All类可以做一些非常相似但&&代替的操作||.

看看反汇编,由于需要调用Equals,发生了相当多的装箱,因此最终比明显的(x == 1) || (x == 2)构造慢.但是,如果你改变一切<T>的来int和更换Equals==,你得到的东西这似乎很好地内嵌到大致相同的速度(x == 1) || (x == 2).