Removing elements from a list by indexes

I need to remove elements from a list based on a delimiter and then remove the previous , delimiter and next elements. In the below case the delimiter is ==

`listex = ['15',  'FXX' , '46'  , 'FXW' , '==' , 'HEAT',  'FXR' , '==' ,'BLAH']`
if "==" in listex:
 ind = listex.index('==')
 ind1 = ind - 1
 ind2 = ind + 1
 indexes = [ind1,ind,ind2]
            for index in sorted(indexes, reverse=True):
               del listex[index]

This outputs …
[‘15’, ‘FXX’ , ‘46’ , ‘FXR’ , ‘==’ ,‘BLAH’]

So only takes the first instance. Is there a way to find all and delete all instances. I’m missing a loop somewhere ?

I just found a solution …

While “==” in listex:

works.

You can avoid the unnecessary sort by just assembling the indices in the correct order in the first place:

indexes = [ind+1, ind, ind-1]

Which also avoids the two temporary variables.

Even better, instead of three deletions you can do just one:

ind = listex.index('==')
del listex[ind-1:ind+2]

Notice that slices listex[start:end] including the start position but exclude the end position, so we need to go one more to ensure we cut three items.

2 Likes

My solution:

def rm_prev_del_next(array, delimiter="=="):
    # edge case: list is empty or None
    if array is None or len(array) <= 0:
        return
    # edge case: list of length one
    if len(array) == 1 and array[0] != delimiter:
        yield array[0]
    for index in range(len(array) - 1):
        # check for delimiters at the edge
        if index == 0 and array[0] != delimiter:
            yield array[0]
            continue
        if (
            index == len(array) - 2
            and array[-1] != delimiter
            and array[-2] != delimiter
        ):
            yield array[-2]
        # check for delimiters in between index 1 and len(array) - 3
        if array[index - 1] != delimiter:
            if array[index + 1] != delimiter:
                if array[index] != delimiter:
                    yield array[index]



array = [
    "15",
    "FXX",
    "46",
    "FXW",
    "==",
    "==",
    "HEAT",
    "FXR",
    "==",
    "BLAH",
    "BLAH",
    "==",
]
new_array = list(rm_prev_del_next(array))
assert new_array == ["15", "FXX", "46"]
1 Like

Thanks for the replies. How would go about looping through the list and extracting elements in mutlipes of 3’s by index the indexes ?
These would then be written to a string.

So for the above list

index = 0
while index < len(listex):
     print (listex[0] , listex[1]  ,listex[2]
     del spbe[0:2]
     index +=3

I can’t any other way to do it. The other methods i’ve involve slicing and creating a new list every n =3 , which does’nt have the desired effect

I came up with this for your first question, Ross. It’s not as pythonic as Steven’s but is possibly more self-evident in its mechanics (other than why it parses through the list backward).
[EDIT: Actually, @steven.daprano’s gives the same result as your original.]

I had to break out idx from the For: index to skip over the deleted listex[idx-1] element, otherwise when the code continues the loop it tries to check if that deleted element == '=='.

idx = len(listex)
for i in range(idx):
    idx -= 1
    if listex[idx] == '==':
        del listex[idx-1:idx+2]
        idx -= 1
print(listex)
1 Like

Is this homework, Ross? These sound like programming exercises.

The code you posted immediately above will throw a syntax error. Have you run it?

spbe[] also doesn’t exist at your Line 4.

You’re offering code so it looks like you’re putting in some work on these, which is good since that’s how you learn to program. If it’s homework, we need to change our approach so we don’t deprive you of the full learning opportunity.

If you end up developing the software that my bank uses when I’m 90 years old, I want you to know your stuff!

1 Like

P.S. I see you’re still using that while: loop construction. I ran your original code with while: and see that it produces the output you need. The question is “why?” (in an academic sense, at least) since that’s a very nonobvious use for while:.

1 Like

I’m not sure why you think this is an unobvious use of while.

In English, Ross’ task is:

“So long as there is a ‘==’ item in the list, remove it and the surrounding two items.”

Or wording it another way:

“While there is a ‘==’ item in the list, …”

So to me this is an extremely obvious and natural way to solve Ross’ task. Not the fastest way, for large lists it does a lot of unneccessary work, but the most natural way. While there is something to delete, delete it.

1 Like

Not homework as such. I’m learning python and doing a project for my club parsing xml’s and extracting equations. Thanks for your help so far.

Well, you’re always more than welcome to ask, Steve. :slightly_smiling_face:

As it turns out, the unobviousness I was suffering stems from the abrupt shift from an iterator context to a pure boolean construction.

While deconstructing all of this so I could express the unobviousness to you, I realized that the While '==' in listex: is interpreting to "while the value '==' exists anywhere in the list listex", which is actually pretty Pythonic. Happily, I wrote this reply and only then read the rest of your post, so I was able to straighten it out for myself, which is always a deeper learning experience.

I suspect Ross had more of an iterative “when” context in mind, though, and that was my first take on it, too. Perhaps he will tell us the honest situation.

Postscript

To illustrate the philosophical iterable case… It appeared at first glance to be a case of using while: as a ‘when:’. This was my failure in not recognizing the paradigm shift from iterable to boolean. So, if it were a “when” iteration loop–which doesn’t exist in Python [1] or any other language that I know of–then it would interpret as “when the iterated item’s value equals '==' then do the code in the Loop body.” That makes straight grammatical sense and, as I said before, I suspect that’s what Ross had in mind when he wrote when '==' in listex: Perhaps he’ll tell us…

[1] but might actually have some merit since one of the superpowers of Python is its List functionality. On the other hand a when: is easily achieved with gating:

for item in lst:
    if lst != 'target': continue
    <terget code>

For what club?
These exercises are a bit random. Is there a practical context or more like doing it for the sake of the activity, like Debate Club?

And how much would you like to discuss the code structures and approaches versus “here’s an answer”?

Also- are you focusing on lists or loops…or both?

Do you know about the range() function, @cheesebird? You could see how to use it with the for: iterator to achieve your multiples of 3’s.

Here are some references:
Python Docs
Geeks for Geeks (pretty straight info)
RealPython (straight and a little more advanced)

@mlgtechuser

Thanks for the tips in the end I adapted the old while loop and deleted the first 3 elements every run until the list was empty.

index = 1
while index < len(listex):
print (listex[0] , listex[1] ,listex[2]
del listex[3]

Will look through the links and see if I can improve things and learn at the same time.

Yes basically I’m parsing XML and extracting all the formulas from them. These are then written to another XML to be used with astronomy club. I ambitiously said I can do it easily, but still not finished after a week.

Parsing is not a problem but I then have to rearrange the formulas i.e.

0.9 < XXX888 should then be reversed.
XXX888 > 8 XXX888 < 9 should be matched and duplicates removed etc.

I’ve got these working but then I find another equation and have to recode things again to make it work for all cases.

So I’m using lots of lists and loops. Trying learn and progress simultaneously.

Who is “Tony” and what have you done with Ross? :face_with_monocle::upside_down_face:
Ross earned some cred by pasting his code in codeblocks from the very first post.

This code just deletes the 4th list element until the list only has three elements and then throws an error because it tries to del a listex[3] that doesn’t exist anymore.

index = 1
while index < len(listex):
    print (listex[0] , listex[1] ,listex[2])
    del listex[3]

Did you post different code than what you settled on?

That sounds like some good training. So it goes with data structures.
STEP 1: Identify what never changes.
STEP 2: Pray that you can find some sort of systematic structure to code around.

1 Like

Sorry I copied the wrong code…

Here is what works for me.

listex = [
    "1", "2" ,"3","11","22","33","111","222","333"
    ]

index = 1
while index <= len(listex):
    print (len(listex))
    print (listex[0] , listex[1] ,listex[2])
    del listex[0:3]

I couldn’t get the range to do the same thing.

Something has gone wrong with my user name when I logged on with Google. I’ll work out how to change it back :slight_smile:

Yeah, that looks like a prototpe of what you described. Just need to assign the strings.

Get Ross to paste the code. He formats it properly and consistently. “Tony” slacked off. It really does matter. The professionals here who answer questions have been using monotext code editors for years and code in variable width type is terrible for reading. Discuss will also mangle your pasted code by removing indents and swapping curly quotation marks in for your plain straight ones that the Python interpreter expects.

I’m in Japan and it’s Monday 2:23am here. Gotta get some sleep. Will be back on line in 10 hours or so.

1 Like

Paste your range() code if you’d like help sorting it out. It sounds like a tool you’ll need in your toolbox for deconstructing those XML files.