我怎样才能写成“x == 1 or 2”用编程语言?

发布于 2024-09-26 10:40:49 字数 491 浏览 0 评论 0原文

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

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

我想这样写“如果x是1或2 => TRUE(否则FALSE)。”

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

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

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

Possible Duplicate:
Why do most programming languages only have binary equality comparison operators?

I have had a simple question for a fairly long time--since I started learning programming languages.

I'd like to write like "if x is either 1 or 2 => TRUE (otherwise FALSE)."

But when I write it in a programming language, say in C,

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

it really works but looks awkward and hard to read. I guess it should be possible to simplify such an or operation, and so if you have any idea, please tell me. Thanks, Nathan

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

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

发布评论

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

评论(22

谁许谁一生繁华 2024-10-03 10:40:49

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

if x in (1, 2):

Python allows test for membership in a sequence:

if x in (1, 2):
独留℉清风醉 2024-10-03 10:40:49

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
{
}

An extension version in C#

step 1: create an extension method

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

step 2: use the extension method

if (x.Either(1,2,3,4,5,6)) 
{
}
else
{
}
向地狱狂奔 2024-10-03 10:40:49

虽然该线程中有许多非常有趣的答案,但我想指出,如果您根据语言在循环内执行这种逻辑,它们可能会对性能产生影响。就计算机理解而言,if (x == 1 || x == 2) 在编译成机器代码时是迄今为止最容易理解和优化的。

While there are a number of quite interesting answers in this thread, I would like to point out that they may have performance implications if you're doing this kind of logic inside of a loop depending on the language. A far as for the computer to understand, the if (x == 1 || x == 2) is by far the easiest to understand and optimize when it's compiled into machine code.

偏爱你一生 2024-10-03 10:40:49

当我开始编程时,我觉得很奇怪,而不是像这样:

(1 < x < 10)

我必须写:

(1 < x && x < 10)

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

所以我相信这样写是完全可以的。

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

这样写还有一个优点,就是其他程序员会很容易理解你写的内容。使用函数来封装它可能只会使事情变得更加复杂,因为其他程序员需要找到该函数并了解它的作用。

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

When I started programming it seemed weird to me as well that instead of something like:

(1 < x < 10)

I had to write:

(1 < x && x < 10)

But this is how most programming languages work, and after a while you will get used to it.

So I believe it is perfectly fine to write

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

Writing it this way also has the advantage that other programmers will understand easily what you wrote. Using a function to encapsulate it might just make things more complicated because the other programmers would need to find that function and see what it does.

Only more recent programming languages like Python, Ruby etc. allow you to write it in a simpler, nicer way. That is mostly because these programming languages are designed to increase the programmers productivity, while the older programming languages' main goal was application performance and not so much programmer productivity.

旧情别恋 2024-10-03 10:40:49

它很自然,但与语言相关

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

混乱的理由

C系统编程语言,并且与硬件相当接近(有趣的是,因为我们过去认为是一种“高级”语言,而不是编写机器代码),它不完全表达

现代高级语言(再次强调,从历史上看,lisp 并不是那么现代,但允许你很好地做到这一点)允许你通过使用内置构造或库支持来完成这些事情(例如,使用范围、元组或类似 Python, Ruby, Groovy, ML 语言Haskell...)。

可能的解决方案

选项 1

您的一个选择是实现一个采用一组值的函数或子例程并检查它们。

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

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

但是,您很快就会看到,这是非常基本的并且不是很灵活:

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

选项 2

复杂性阶梯(就语言而言)更高一级,另一种选择是使用 预处理器 位于C (或 C++)来实现类似的行为,但要注意副作用

其他选项

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

下一步是使用 模板,通过单个实现在不同类型上执行此操作。

然后从那里继续学习更高级别的语言


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

通常,支持函数式编程的语言将会构建-出于显而易见的原因,支持这类事情。

或者只是学会接受某些语言可以做其他语言不能做的事情,并且根据工作和环境,事情就是这样。它主要是语法糖,你无能为力。此外,随着时间的推移,一些语言将通过更新其规范来解决其缺点,而另一些语言则只会停滞不前。

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

It's Natural, but Language-Dependent

Your approach would indeed seem more natural but that really depends on the language you use for the implementation.

Rationale for the Mess

C being a systems programming language, and fairly close to the hardware (funny though, as we used to consider a "high-level" language, as opposed to writing machine code), it's not exactly expressive.

Modern higher-level languages (again, arguable, lisp is not that modern, historically speaking, but would allow you to do that nicely) allow you to do such things by using built-in constructs or library support (for instances, using Ranges, Tuples or equivalents in languages like Python, Ruby, Groovy, ML-languages, Haskell...).

Possible Solutions

Option 1

One option for you would be to implement a function or subroutine taking an array of values and checking them.

Here's a basic prototype, and I leave the implementation as an exercise to you:

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

However, as you will quickly see, this is very basic and not very flexible:

  • it works only on integers,
  • it works only to compare identical values.

Option 2

One step higher on the complexity ladder (in terms of languages), an alternative would be to use pre-processor macros in C (or C++) to achieve a similar behavior, but beware of side effects.

Other Options

A next step could be to pass a function pointer as an extra parameter to define the behavior at call-point, define several variants and aliases for this, and build yourself a small library of comparators.

The next step then would be to implement a similar thing in C++ using templates to do this on different types with a single implementation.

And then keep going from there to higher-level languages.


Pick the Right Language (or learn to let go!)

Typically, languages favoring functional programming will have built-in support for this sort of thing, for obvious reasons.

Or just learn to accept that some languages can do things that others cannot, and that depending on the job and environment, that's just the way it is. It mostly is syntactic sugar, and there's not much you can do. Also, some languages will address their shortcomings over time by updating their specifications, while others will just stall.

Maybe a library implements such a thing already and that I am not aware of.

葵雨 2024-10-03 10:40:49

这是很多有趣的选择。我很惊讶没有人提到 switch...case - 所以这里是:

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

that was a lot of interesting alternatives. I am surprised nobody mentioned switch...case - so here goes:

switch(x) {
case 1:
case 2:
  // do your work
  break;
default:
  // the else part
}
  1. it is more readable than having a
    bunch of x == 1 || x == 2 || ...
  2. more optimal than having a
    array/set/list for doing a
    membership check
信仰 2024-10-03 10:40:49

我怀疑我是否会这样做,但为了回答你的问题,这里有一种在 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) 构造。但是,如果将所有 更改为 int 并将 Equals 替换为 == ,你会得到一些看起来内联得很好的东西,其速度与 (x == 1) || 大致相同。 (x == 2)。

I doubt I'd ever do this, but to answer your question, here's one way to achieve it in C# involving a little generic type inference and some abuse of operator overloading. You could write code like this:

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

Where the Any class is defined as:

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(); }
    }
}

You could conceivably have a number of overloads of the Any.Of method to work with 3, 4, or even more arguments. Other operators could be provided as well, and a companion All class could do something very similar but with && in place of ||.

Looking at the disassembly, a fair bit of boxing happens because of the need to call Equals, so this ends up being slower than the obvious (x == 1) || (x == 2) construct. However, if you change all the <T>'s to int and replace the Equals with ==, you get something which appears to inline nicely to be about the same speed as (x == 1) || (x == 2).

陈甜 2024-10-03 10:40:49

呃,有什么问题吗?哦,好吧,如果你真的经常使用它并且讨厌它的外观,请在 c# 中执行类似的操作:

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

在使用它的地方:

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

或者在另一种语言中执行类似的操作:)。

Err, what's wrong with it? Oh well, if you really use it a lot and hate the looks do something like this in c#:

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

and in places where you use it:

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

Or something like that in another language :).

树深时见影 2024-10-03 10:40:49

在 php 中,您可以使用

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

In php you can use

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

夏末的微笑 2024-10-03 10:40:49

据我所知,C 中没有内置的方法可以做到这一点。您可以添加自己的内联函数来扫描整数数组中是否有等于 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'

As far as I know, there is no built-in way of doing this in C. You could add your own inline function for scanning an array of ints for values equal to x....

Like so:

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'
咿呀咿呀哟 2024-10-03 10:40:49

在 T-SQL 中

where x in (1,2)

In T-SQL

where x in (1,2)
把回忆走一遍 2024-10-03 10:40:49

在COBOL中(我已经很长时间没有简单地浏览过COBOL了,所以我在这里可能有一两个细节错误):

IF X EQUALS 1 OR 2
...

所以语法绝对是可能的。那么问题就归结为“为什么不更频繁地使用它?”

嗯,问题是,解析这样的表达式有点麻烦。请注意,不是像这样单独站立时,而是在复合表达中。语法开始变得不透明(从编译器实现者的角度来看),语义也变得非常复杂。 IIRC,如果您使用这样的语法,许多 COBOL 编译器甚至会警告您,因为存在潜在的问题。

In COBOL (it's been a long time since I've even glanced briefly at COBOL, so I may have a detail or two wrong here):

IF X EQUALS 1 OR 2
...

So the syntax is definitely possible. The question then boils down to "why is it not used more often?"

Well, the thing is, parsing expressions like that is a bit of a bitch. Not when standing alone like that, mind, but more when in compound expressions. The syntax starts to become opaque (from the compiler implementer's perspective) and the semantics downright hairy. IIRC, a lot of COBOL compilers will even warn you if you use syntax like that because of the potential problems.

心清如水 2024-10-03 10:40:49

在.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 );

In .Net you can use 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 );

Although personally I think the basic || is simple enough:

bool result = ( x == 1 || x == 2 );
゛时过境迁 2024-10-03 10:40:49

谢谢伊格纳西奥!我将其翻译成 Ruby:

[ 1, 2 ].include?( x )

它也可以工作,但我不确定它是否看起来清晰&普通的。如果您了解Ruby,请指教。另外,如果有人知道如何用 C 语言编写这个,请告诉我。谢谢。 -内森

Thanks Ignacio! I translate it into Ruby:

[ 1, 2 ].include?( x )

and it also works, but I'm not sure whether it'd look clear & normal. If you know about Ruby, please advise. Also if anybody knows how to write this in C, please tell me. Thanks. -Nathan

甲如呢乙后呢 2024-10-03 10:40:49

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;

这个版本非常可读并且简洁我会使用它而不是 || 运算符。

Perl 5 with Perl6::Junction:

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

Perl 6:

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

This version is so readable and concise I’d use it instead of the || operator.

我还不会笑 2024-10-03 10:40:49

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

if x in [1, 2] then

几十年来没有接触过 Pascal 编译器,所以语法可能不正确)

Pascal has a (limited) notion of sets, so you could do:

if x in [1, 2] then

(haven't touched a Pascal compiler in decades so the syntax may be off)

浅忆流年 2024-10-03 10:40:49

尝试仅使用一个非按位布尔运算符(不建议,未测试):

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。

A try with only one non-bitwise boolean operator (not advised, not tested):

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

The (x&3) ^ x part should be equal to 0, this ensures that x is between 0 and 3. Other operands will only have the last bit set.

The ((x>>1)&1) ^ (x&1) ^ 1 part ensures last and second to last bits are different. This will apply to 1 and 2, but not 0 and 3.

从此见与不见 2024-10-03 10:40:49

您说符号 (x==1 || x==2) 是“尴尬且难以阅读”。我不敢苟同。它与自然语言不同,但非常清晰且易于理解。你只需要像计算机一样思考。

此外,此线程中提到的符号(例如 x in (1,2))在语义上与您真正要问的不同,它们询问 x 是否是 的成员>set (1,2),这不是你要问的。您要问的是if x equals to 1 or to 2,这在逻辑上(和语义上)相当于if x equals to 1 or x equals to 2< /code> 翻译为 (x==1 || x==2)

You say the notation (x==1 || x==2) is "awkward and hard to read". I beg to differ. It's different than natural language, but is very clear and easy to understand. You just need to think like a computer.

Also, the notations mentioned in this thread like x in (1,2) are semantically different then what you are really asking, they ask if x is member of the set (1,2), which is not what you are asking. What you are asking is if x equals to 1 or to 2 which is logically (and semantically) equivalent to if x equals to 1 or x equals to 2 which translates to (x==1 || x==2).

影子的影子 2024-10-03 10:40:49

在java中:

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

In java:

 List list = Arrays.asList(new Integer[]{1,2});
 Set set = new HashSet(list);
 set.contains(1)
仲春光 2024-10-03 10:40:49

我有一个经常使用的宏,它有点接近你想要的。

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

ISBETWEEN(x, 1, 2) 如果 x 是 1 或 2, 将返回 true。

I have a macro that I use a lot that's somewhat close to what you want.

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

ISBETWEEN(x, 1, 2) will return true if x is 1 or 2.

千秋岁 2024-10-03 10:40:49

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

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

如果一种语言具有“如果变量是多个常量之一”的构造,我希望编译器使用上述代码模式。遗憾的是,通用语言中不存在这样的结构。

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

Neither C, C++, VB.net, C#.net, nor any other such language I know of has an efficient way to test for something being one of several choices. Although (x==1 || x==2) is often the most natural way to code such a construct, that approach sometimes requires the creation of an extra temporary variable:

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

Certainly an optimizer should be able to effectively get rid of the temporary variable (shove it in a register for the brief time it's used) but I still think that code is ugly. Further, on some embedded processors, the most compact and possibly fastest way to write (x == const1 || x==const2 || x==const3) is:

  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

That approach require two more instructions for each constant; all instructions will execute. Early-exit tests will save time if the branch is taken, and waste time otherwise. Coding using a literal interpretation of the separate comparisons would require four instructions for each constant.

If a language had an "if variable is one of several constants" construct, I would expect a compiler to use the above code pattern. Too bad no such construct exists in common languages.

(note: Pascal does have such a construct, but run-time implementations are often very wasteful of both time and code space).

穿透光 2024-10-03 10:40:49

返回x === 1 || JavaScript 中的 x === 2

return x === 1 || x === 2 in javascript

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