Why Does This Not Work as an Array Membership Test

Why does this not work as an array membership test?

This is a chained comparison. You may have known that you can do

1 < 2 < 3

in Python, and it's equivalent to (1 < 2) and (2 < 3). (Or maybe you didn't. Now you know.) Well, the same thing applies to in and ==.

5 in [1, 2, 3, 4] == False

is equivalent to

(5 in [1, 2, 3, 4]) and ([1, 2, 3, 4] == False)

Since [1, 2, 3, 4] is not equal to False, the whole expression evaluates to False.

Cannot test python list element membership when element contains numpy array

Simplified:

def my_in(obj, container):
for elem in container:
if bool(my_compare_equal(obj, elem)):
return True
return False

def my_compare_equal(obj, elem):
if id(obj) == id(elem):
return True
return obj.__eq__(elem)

For more datails, see list_contains and then PyObject_RichCompareBool, PyObject_RichCompare, do_richcompare

"Pseudo-execution" steps:

c = [AA('x', np.arange(3)),
AA('x', np.arange(3)),
AA('y', np.arange(3))]

c[0] in c
# explain:
my_in(obj=c[0], container=c)
# for loop:

# 0-iteration:
# elem = c[0]
my_compare_equal(obj=c[0], elem=c[0])
# (id(c[0]) == id(c[0])) == True
# --> True
bool(True)
# True.__bool__()
# --> True
# --> True

c[1] in c
# explain:
my_in(obj=c[1], container=c)
# for loop:

# 0-iteration:
# elem = c[0]
my_compare_equal(obj=c[1], elem=c[0])
# (id(c[1]) == id(c[0])) == False
# c[1].__eq__(c[0])
# compare tuples element by element:
# 0-iteration:
my_compare_equal('x', 'x') == True
# 1-iteration:
my_compare_equal(np.arange(3), np.arange(3))
# (id(np.arange(3)) == id(np.arange(3))) == False
# np.arange(3).__eq__(np.arange(3))
# --> np.ndarray([True, True, True])
bool(np.ndarray([True, True, True]))
# np.ndarray([True, True, True]).__bool__()
raise ValueError("The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()")

c[2] in c
# explain:
my_in(obj=c[2], container=c)
# for loop:

# 0-iteration:
# elem = c[0]
my_compare_equal(obj=c[2], elem=c[0])
# (id(c[2]) == id(c[0])) == False
# c[2].__eq__(c[0])
# compare tuples element by element:
# 0-iteration:
my_compare_equal('y', 'x') == False
# --> False
# --> False

# 1-iteration:
# analogiusly as 0-iteration:
my_compare_equal(obj=c[2], elem=c[1])
# --> False

# 2-iteration:
my_compare_equal(obj=c[2], elem=c[2])
# (id(c[2]) == id(c[2])) == True
# --> True
# --> True

How do I check if an array includes a value in JavaScript?

Modern browsers have Array#includes, which does exactly that and is widely supported by everyone except IE:

console.log(['joe', 'jane', 'mary'].includes('jane')); //true

Array.Contains() is always false

I've taken your line of code that isn't working and copied it verbatim. I've then taken the data that you say is in the WordArray and guessString variables and set those up. Then I ran this:

var WordArray = new [] { "WHICH", "THERE", "THEIR", "ABOUT" };
var guessString= "THERE";
bool match = WordArray.Contains(guessString);
Console.WriteLine(match);

match comes out True.

Your variables do not contain the data you think they do.

It's likely that the content that you call .Split('\n') on actually contains Windows end of line markers, so a combination of "\r\n". Since you only split on '\n' it's likely that the '\r' remains in your strings and hence "THERE" does not match "THERE\r".

Try this instead:

.Split(new[] { Environment.NewLine }, StringSplitOptions.None);

If your code is run on either Windows or on Linux the above line works. Just watch out for files that mix the endings.

How do I check whether an array contains a string in TypeScript?

The same as in JavaScript, using Array.prototype.indexOf():

console.log(channelArray.indexOf('three') > -1);

Or using ECMAScript 2016 Array.prototype.includes():

console.log(channelArray.includes('three'));

Note that you could also use methods like showed by @Nitzan to find a string. However you wouldn't usually do that for a string array, but rather for an array of objects. There those methods were more sensible. For example

const arr = [{foo: 'bar'}, {foo: 'bar'}, {foo: 'baz'}];
console.log(arr.find(e => e.foo === 'bar')); // {foo: 'bar'} (first match)
console.log(arr.some(e => e.foo === 'bar')); // true
console.log(arr.filter(e => e.foo === 'bar')); // [{foo: 'bar'}, {foo: 'bar'}]

Reference

Array.find()

Array.some()

Array.filter()

Checking whether array contains incremental elements if one is removed

Creating a new array seems overkill. I would first define a function that verifies at which index a given array violates being incremental.

Then check if there is a second violation after that. If so, return false.

With just one violation, return true when it occurs between the first two or last two values in the array.

In all other cases, verify that removing either of the two involved values resolves the violation.

Code:

// Return the index where the value is not greater than its predecessor
function violation(a, start=0) {
for (let i = start + 1; i < a.length; i++) {
if (a[i - 1] >= a[i]) return i;
}
return 0;
}

function solution(a) {
let i = violation(a);
return !i || !violation(a, i) && (i==1 || i==a.length-1
|| a[i-2] < a[i] || a[i-1] < a[i+1]);
}

//TEST CASES
let tests = [
[1, 2, 3, 4, 5, 3, 5, 6],
[40, 50, 60, 10, 20, 30],
[1, 2, 3, 4, 3, 6],
[1, 4, 10, 4, 2]
];

for (let test of tests) {
console.log(solution(test));
}

When checking if an item does not exist in a list, why doesn't this code work - if item in list == False:

This is due to comparison operator chaining. From the documentation:

Comparisons can be chained arbitrarily, e.g., x < y <= z is equivalent to x < y and y <= z, except that y is evaluated only once (but in both cases z is not evaluated at all when x < y is found to be false).

You are assuming that the 9 in list == False expression is executed as (9 in list) == False but that is not the case.

Instead, python evaluates that as (9 in list) and (list == False) instead, and the latter part is never True.

You really want to use the not in operator, and avoid naming your variables list:

if 9 not in lst:


Related Topics



Leave a reply



Submit