Equality Comparison Between Multiple Variables

Equality comparison between multiple variables

KennyTM is correct, there is no other simpler or more efficient way.

However, if you have many variables, you could also build an array of the values and use the IEnumerable.All method to verify they're all 1. More readable, IMO.

if (new[] { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10 }.All(x => x == 1))

Instead of

if(v1 == 1 && v2 == 1 && v3 == 1 && v4 == 1 && v5 == 1 && v6 == 1 && v7 == 1 && v8 == 1 && v9== 1 && v10 == 1)

How to test multiple variables for equality against a single value?

You misunderstand how boolean expressions work; they don't work like an English sentence and guess that you are talking about the same comparison for all names here. You are looking for:

if x == 1 or y == 1 or z == 1:

x and y are otherwise evaluated on their own (False if 0, True otherwise).

You can shorten that using a containment test against a tuple:

if 1 in (x, y, z):

or better still:

if 1 in {x, y, z}:

using a set to take advantage of the constant-cost membership test (i.e. in takes a fixed amount of time whatever the left-hand operand is).

Explanation

When you use or, python sees each side of the operator as separate expressions. The expression x or y == 1 is treated as first a boolean test for x, then if that is False, the expression y == 1 is tested.

This is due to operator precedence. The or operator has a lower precedence than the == test, so the latter is evaluated first.

However, even if this were not the case, and the expression x or y or z == 1 was actually interpreted as (x or y or z) == 1 instead, this would still not do what you expect it to do.

x or y or z would evaluate to the first argument that is 'truthy', e.g. not False, numeric 0 or empty (see boolean expressions for details on what Python considers false in a boolean context).

So for the values x = 2; y = 1; z = 0, x or y or z would resolve to 2, because that is the first true-like value in the arguments. Then 2 == 1 would be False, even though y == 1 would be True.

The same would apply to the inverse; testing multiple values against a single variable; x == 1 or 2 or 3 would fail for the same reasons. Use x == 1 or x == 2 or x == 3 or x in {1, 2, 3}.

How do I check the equality of three values elegantly?

A note beforehand:

Your last proposed solution is the shortest, clearest and most efficient way to compare if 3 values are equal:

if a == b && a == c {
fmt.Println("Clearest: all 3 are equal")
}

or alternatively (to your liking):

if a == b && b == c {
fmt.Println("Clearest: all 3 are equal")
}

The rest of this answer (what follows) is just toying with the language specification and the language's capabilities, presenting what I find fun and creative. They do not attempt to provide a superior solution.


Try all the examples below on the Go Playground. The examples build on the terms and the result of the comparisons which are defined in Spec: Comparison operators.

General note: in the examples below I used the type interface{} which will work whatever type your values have (a, b and c), but if you know they are of type int for example, you can use that specific type too (which would improve efficiency and shorten the length of the examples).

With a map as a set

if len(map[interface{}]int{a: 0, b: 0, c: 0}) == 1 {
fmt.Println("Map set: all 3 are equal")
}

Effectively we put all comparable values into a map as keys, and if all are equal, there will be only 1 pair in the map, so the "length" of the map will be 1. The value type of the map doesn't play any role here, it could be anything. I used int because this results in the shortest composite literal (that defines the map value).

This solution is flexible as you can use any number of values to test if all are equal, not just 3.

With arrays

Arrays are comparable (unlike slices):

if [2]interface{}{a, b} == [2]interface{}{b, c} {
fmt.Println("Arrays: all 3 are equal")
}

The result of the array comparison will be true if a == b and b == c (if the corresponding elements are equal).

Note that you can apply this method on any number of values as well. It would look like this for 5 values:

if [4]interface{}{a, b, c, d} == [4]interface{}{b, c, d, e} {
fmt.Println("Arrays: all 5 are equal")
}

With a tricky map

if map[interface{}]bool{a: b == c}[b] {
fmt.Println("Tricky map: all 3 are equal")
}

This composite literal will assign the comparision result of b == c to the key a. And we ask the value associated with the key b. If a == b, the result of the indexing expression will be the result of b == c, that is, whether all 3 values are equal. If a != b, then the zero value of the value type will be the result, which is false in case of bool, properly telling that all 3 values are not equal.

With anonymous structs

struct values are also comparable, so:

if struct{ a, b interface{} }{a, b} == struct{ a, b interface{} }{b, c} {
fmt.Println("Anon structs: all 3 are equal")
}

With (named) structs

If we define a simple struct beforehand:

type P struct{ a, b interface{} }

Comparison will be much more compact:

if (P{a, b} == P{b, c}) {
fmt.Println("Structs: all 3 are equal")
}

(Note that the expression of the if statement must be put in parenthesis to avoid parsing ambiguity - else it's a compile time error!)

With slices

Slices are not comparable, so we will need to borrow some help from reflect.DeepEqual():

if reflect.DeepEqual([]interface{}{a, b}, []interface{}{b, c}) {
fmt.Println("Slices: all 3 are equal")
}

With a helper function

func AllEquals(v ...interface{}) bool {
if len(v) > 1 {
a := v[0]
for _, s := range v {
if a != s {
return false
}
}
}
return true
}

And using it:

if AllEquals(a, b, c) {
fmt.Println("Helper function: all 3 are equal")
}

This solution is also flexible, you can call AllEquals() with any number of values.

Note that we can make the AllEquals() function more compact if we're also willing to call reflect.DeepEqual() here:

func AllEquals2(v ...interface{}) bool {
if len(v) < 2 {
return true
}
return reflect.DeepEqual(v[:len(v)-1], v[1:])
}

What's the prettiest way to compare one value against multiple values?

Don't try to be too sneaky, especially when it needlessly affects performance.
If you really have a whole heap of comparisons to do, just format it nicely.

if (foobar === foo ||
foobar === bar ||
foobar === baz ||
foobar === pew) {
//do something
}

How to compare a value to several other values in one line in Kotlin

I think the simplest way is with the in operator:

a in listOf(b, c)

you can include as many items as you want inside the list.

Compare multiple values in one condition

You can create an usefull extension function:

public static bool EqualsAll<T>(this T val, params T[] values)
{
return values.All(v => v.Equals(val));
}

call it like:

bool res = 123.EqualsAll(int1,int2,int3);

Most efficient way to compare a variable to multiple values?

If the values you want to check are sufficiently small, you could create a bit mask of the values that you seek and then check for that bit to be set.

Suppose, you care about a couple of groups.

static const unsigned values_group_1 = (1 << 1) | (1 << 2) | (1 << 3);
static const unsigned values_group_2 = (1 << 4) | (1 << 5) | (1 << 6);
static const unsigned values_group_3 = (1 << 7) | (1 << 8) | (1 << 9);
if ((1 << value_to_check) & values_group_1) {
// You found a match for group 1
}
if ((1 << value_to_check) & values_group_2) {
// You found a match for group 2
}
if ((1 << value_to_check) & values_group_3) {
// You found a match for group 3
}

This approach works best for values that don't exceed the natural size your CPU likes to work with. This would typically be 64 in modern times, but may vary depending upon the specifics of your environment.

Easy way to compare values of more than 3 variables?

how about something like this:

if (Array.TrueForAll<int>(new int[] {a, b, c, d, e, f, g, h, i, j, k },
val => (a == val))) {
// do something
}


Related Topics



Leave a reply



Submit