Home > Enterprise >  check if element is in anywhere the list
check if element is in anywhere the list

Time:12-01

I have two lists:

expected = ["apple", "banana", "pear"]
actual = ["banana_yellow", "apple", "pear_green"]

I'm trying to assert that expected = actual. Even though the color is added at the end to some elements, it should still return true.

Things I tried:

for i in expected:
   assert i in actual

I was hoping something like this would work but it's trying to match the first element apple to banana and returns false rather than checking the entire list and returns true if there is apple anywhere in the list. I was hoping someone can help?

CodePudding user response:

I suggest a custom assertion method..

This is a bit more than you need, but also a bit more flexible.

  • Order of the entries is irrelevant
  • How the color is added is irrelevant (e.g. by dash, underscore, ...)

It still has the flaw that, if you have the color orange added to carot and are looking for orange, it would also assert sucessfully. For such cases you need to tailor the method to your actual needs. (e.g. replace the substring in string by string.startwith(substring) etc. However, this should give you a starting point:

def assert_matching_list_contents(expected: list, actual: list) -> None:
    if len(expected) != len(actual):
        raise AssertionError('Length of the lists does not match!')

    for expected_value in expected:
        if not any(expected_value in entry for entry in actual):
            raise AssertionError(f'Expected entry "{expected_value}" not found')

expectation = ["apple", "banana", "pear"]
current = ["banana_yellow", "apple", "pear_green"]
assert_matching_list_contents(expectation, current)

CodePudding user response:

You can use .startswith, along with sorted lists to find it.

expected = ["apple", "banana", "pear"]
actual = ["banana_yellow", "apple", "pear_green"]
expected.sort() # just looking for prefixes
actual.sort()
count = 0
for i in actual:
    if i.startswith(expected[count]): # prefix matches!
        count =1 # move to next prefix
if count != len(expected): # since it didn't find all expected
    print("Nope!")
    assert False

It works because it just skips extras in actual, but count gets stuck if it can't find the prefix in actual, leading count to never reach the end of expected.

CodePudding user response:

Try this:

def isequal(actual: list, expected: list) -> bool:
    actual.sort()
    expected.sort()
    if len(actual) != len(expected):
        return False
    for i, val in enumerate(expected):
        if not actual[i].startswith(val):
            return False
    return True

print(isequal(actual, expected))

CodePudding user response:

expected = ["apple", "banana", "pear"]
actual = ["banana_yellow", "apple", "pear_green", 'orange']

for act in actual:
    if not act.startswith(tuple(expected)):
        print(act)
>>>
orange

If you want it to work in the opposite way,

expected = ["apple", "banana", "pear", 'grapes']
actual = ["banana_yellow", "apple", "pear_green", 'orange']
expected_ = set(expected)
for act in actual:
    for exp in expected:
        if act.startswith(exp):
            expected_.discard(exp)
            break
assert not(expected_), f"{expected_} are not found in actual and "   f"{set(expected)-expected_} are found in actual"
>>>
AssertionError: {'grapes'} are not found in actual and {'apple', 'pear', 'banana'} are found in actual

Another way,

expected = ["apple", "banana", "pear", 'grapes']
actual = ["banana_yellow", "apple", "pear_green", 'orange']
for exp in expected:
    assert [exp for act in actual if act.startswith(exp)], f'{exp} not found'
>>>
AssertionError: grapes not found
  • Related