How to remove items from a list where partial matches for items exist in the list

Viewed 50

If I have a list that contains items within it that have partial matches of other items in the list, such as below where 'bob' is a partial match within 'bob1' and 'bob2', I want to remove these items with partial matches ('bob1', 'bob2', 'peter2') e.g. I want to go from this:

lst = ['bob', 'bob1', 'bob2', 'peter', 'peter2']`

to this:

lst = ['bob', 'peter']

I have this that works, but I was wondering if there's a cleaner way?

lst = ['bob', 'bob1', 'bob2', 'peter', 'peter2']

removeIndices = []
for i, itemi in enumerate(lst):
    for j, itemj in enumerate(lst):
        if itemi in itemj and itemi != itemj:
            removeIndices.append(j)

for i in sorted(removeIndices, reverse=True):
    del lst[i]
2 Answers

You can use all() with a list that accumulates the result:

result = []

for item in lst:
    if all(substr not in item for substr in result):
        result.append(item)

This outputs:

['bob', 'peter']

This has two advantages over your existing approach:

  1. There's no need to repeatedly call del on the original list. If you want to retain the original list, you can. (Repeatedly calling del is also quite slow.)
  2. A double for loop isn't necessary. This syntax is (in my opinion) much cleaner and more intuitive.

The solution by @BrokenBenchmark works only for sorted lists. Here is a solution that works for unsorted lists as well.

lst = ['peter2', 'bob2', 'bob', 'bob1', 'peter']

[item for item in lst if sum(substr not in item for substr in lst)==len(lst)-1]

Output:

['bob', 'peter']
Related