Python: Append to list only if multiple elements are not in another list

Viewed 134

I am trying to create a new list based on a subset of elements. The selection criteria is a partial string. I have a working example, but I am trying to code this in a cleaner way such that the selection criteria itself is a list of elements.

I want the source list element (which is itself a list) to be added to the new list only if multiple substrings are not present in any of the source list sub-elements.

Here is my working example code:

links = [['abc', 'def'], ['ghi', 'jkl'], ['def', 'xyz']]

sublinks = []
for link in links:
    if ((('ab' not in link[0]) and ('ab' not in link[1])) and\
        (('xy' not in link[0]) and ('xy' not in link[1]))):
        sublinks.append(link)

From the links list, this achieves the result of appending only the element ['ghi', 'jkl'] since it is the only element from the source list that passes the matching criteria of elements not containing ab or xy in any of the sub-elements.

The example code shows the logic I am trying to achieve, but I would instead like to place ab and xy into a list so that I can specify an arbitrary number of matching criteria. The format of the source list (a list of lists with two elements) will remain the same.

I have spent several hours trying to answer my own question, searching stackoverflow, trying to figure it out on my own, but I haven't had any success yet and any help is greatly appreciated! Thank you

2 Answers

Here is a one liner ..only if I have understood the problem correctly. Please use a bigger "links" list to test this out.

links = [['abc', 'def'], ['ghi', 'jkl'], ['def', 'xyz']]

FinalList = list(filter(lambda x: not any(['ab' in i for i in x]) and not any(['xy' in i for i in x]), links))
print(FinalList)

Gives output as

[['ghi', 'jkl']]

Edit

After I realised that you want the negated terms in a list, I changed the code. The below will also work. In the below code the most important lists are "links" which you want to filter and "Negation_List" which will have terms which you want to avoid.

links = [['abc', 'def'], ['ghi', 'jkl'], ['mno','pqr'],['mno','ghi'],['pqr','jkl'], ['def', 'xyz']]
Negation_List = ['ab','xy','mn','pq']
FinalList = list(filter(lambda x: all(not any([eachNegation in i for i in x]) for eachNegation in Negation_List), links))
print(FinalList)

Gives output as

[['ghi', 'jkl']]

Firstly, create a new list containing the criteria:

criteria_list = ['ab', 'xy']

The replace your for loop with this:

for link in links:
    in_list = True
    for criteria_item in criteria_list:
        for item in link:
            if criteria_item in item:
                in_list = False
            
    if in_list:
        sublinks.append(link)

This will loop through each sub-element in the 'links' list, checking each of these elements against all of the items in the criteria_list, only adding the whole sub-list to sublinks if none of the items are in the criteria_list.

Related