2

My list consists on several items:

["book","rule","eraser","clipboard","pencil",etc]

Let say I have an element ["book"] and I want to match with another element ["rule"] with the same len (4). then I want to remove both elements from the list.

["eraser","clipboard","pencil",etc]

I tried using a for loop and zip(lists, lists[1:]) but I can only remove the elements next to each other while other elements (like papers and pencil, len = 6) are never removed.

I want to remove same length words and have a final list with only the words whose length has no match or found no pair. For example:

["book","rule","eraser","clipboard","pencil","book"]

then the final list will be:

["clipboard","book"]

as book and clipboard found no pair.

Dude Rar
  • 81
  • 6
  • 1
    If I understand you correctly, do you want to remove all words which share same length? – Andrej Kesely Aug 16 '23 at 23:30
  • 2
    Make a dictionary that maps lengths to the list of all elements with that length. Then remove all the strings that are in dictionary elements whose length is > 1. – Barmar Aug 16 '23 at 23:37
  • @Andrej Kesely Yes, I edited the question. I want to remove same length words and have a final list with only the words whose length has no match or found no pair. – Dude Rar Aug 16 '23 at 23:38
  • 1
    Why is `book` in the final list? It has the same length as `rule` – Barmar Aug 16 '23 at 23:43
  • @Barmar because book has already found a pair. – Dude Rar Aug 16 '23 at 23:44
  • 1
    So if there are 3 items with the same length, you remove the first 2? – Barmar Aug 16 '23 at 23:45
  • @Barmar Yes and if I were to have another "rule" then both "book" and "rule" get deleted. They have to be unique, book can only pair with rule and both get deleted. – Dude Rar Aug 16 '23 at 23:48
  • _I tried using a for loop and zip(lists, lists[1:])_ Show us the **actual full code** you tried. Otherwise if you only give a broad description of what you tried, we can only guess at what you did wrong, because **details matter**. – John Gordon Aug 17 '23 at 01:08

3 Answers3

5

Much simpler, think of it as turning on or off a flag. If the flag is on, you turn it off by deleting. If it's off, you turn it on by adding the word. Flags are based on same length:

lst = ["book", "rule", "eraser", "clipboard", "pencil", "book"]
output = {}
for item in lst:
    length = len(item)
    popped = output.pop(length, None)
    if popped is None:
        output[length] = item
print(list(output.values()))
Bharel
  • 23,672
  • 5
  • 40
  • 80
  • 1
    I like this, it's not quite as cryptic as the accepted answer. – Barmar Aug 17 '23 at 01:41
  • 1
    A maybe easier to understand variant: `if length in output: del output[length] else: output[length] = item` (4 lines with correct indentation) – mozway Aug 17 '23 at 02:32
  • this will remove "book" if one more entry is present and even though it has a pair, for example, lst = ["book", "rule", "eraser", "clipboard", "pencil", "book", "book"], the output is ['clipboard'] – KRG Aug 17 '23 at 03:01
  • @KRG it's supposed to remove all pairs by length, it's good – Bharel Aug 17 '23 at 17:55
  • @mozway I wanted to prevent 2 dictionary lookups if it exists. Premature optimization? Maybe. – Bharel Aug 17 '23 at 17:58
1

You can try:

from collections import Counter

lst = ["book", "rule", "eraser", "clipboard", "pencil", "book"]

c = {k: v % 2 for k, v in Counter(map(len, lst)).items()}

out = []
for v in reversed(lst):
    if c[len(v)] == 1:
        out.append(v)
    c[len(v)] -= 1


print(out[::-1])

Prints:

['clipboard', 'book']
Andrej Kesely
  • 168,389
  • 15
  • 48
  • 91
  • 1
    This will remove "book" if one more entry is present and even though it has a pair, for example, lst = ["book", "rule", "eraser", "clipboard", "pencil", "book", "book"], the output is ['clipboard']. – KRG Aug 17 '23 at 03:03
0
input_list = ["book", "rule", "eraser", "clipboard", "pencil", "book"]
output_list=[]

#Each entry in list
for i,val_i in enumerate(input_list):
    len_match=False
    pair_match=False
    #Compared to each entry in the list
    for j,val_j in enumerate(input_list):
        #same index skip
        if i ==j:
            continue
        #found value match
        if val_i==val_j:
            pair_match= True
            break
        #found same length
        if len(val_i) == len(val_j):
            len_match = True
            break
    
    #if found pair or no length match add to output list
    if pair_match or (not len_match):
        output_list.append(val_i)

print(output_list)

output

['clipboard', 'book']
KRG
  • 655
  • 7
  • 18