-2

I am doing a python code to basically filter out the items with the lowest values this code should work, but some weird stuff is happening for example some things from item 1 are being removed and the same is being removed from item two. any help would be appreciated. this question is a duplicate the answers can be seen here How to remove items from a list while iterating?.

items=[['Yellow Goblin Egg', 25000], ['Yellow Goblin Egg', 46000], ['Yellow Goblin Egg', 46000], ['Yellow Goblin Egg', 46000], ['Yellow Goblin Egg', 46000], ['Yellow Goblin Egg', 46000], ['Yellow Goblin Egg', 46000], ['Yellow Goblin Egg', 50000], ['Yellow Goblin Egg', 58000], ['Yellow Goblin Egg', 59000], ['Yellow Goblin Egg', 60000], ['Yellow Goblin Egg', 60000], ['Yellow Goblin Egg', 70000], ['Yellow Goblin Egg', 70000], ['Yellow Goblin Egg', 72000], ['Yellow Goblin Egg', 73000], ['Yellow Goblin Egg', 73000], ['Yellow Goblin Egg', 73000], ['Yellow Goblin Egg', 73000], ['Yellow Goblin Egg', 73000], ['Yellow Goblin Egg', 73000], ['Yellow Goblin Egg', 73000], ['Yellow Goblin Egg', 73000], ['Yellow Goblin Egg', 73000], ['Yellow Goblin Egg', 73000], ['Yellow Goblin Egg', 74000], ['Yellow Goblin Egg', 75000], ['Yellow Goblin Egg', 80000], ['Yellow Goblin Egg', 130000], ['Yellow Goblin Egg', 200000], ['Yellow Repelling Candle', 1300000], ['Yellow Repelling Candle', 1500000], ['Forceful Yellow Crab Hat of Celebration', 14999999], ['Hurtful Yellow Crab Hat of Celebration', 15000000], ['Bloody Yellow Crab Hat of Celebration', 15000000], ['Yellow Crab Hat of Celebration', 15000000], ['Itchy Yellow Crab Hat of Celebration', 16600000], ['Itchy Yellow Crab Hat of Celebration', 16800000], ['Bloody Yellow Crab Hat of Celebration', 17777777], ['Yellow Crab Hat of Celebration', 18000000], ['Yellow Crab Hat of Celebration', 18990000], ['Yellow Crab Hat of Celebration', 19000000], ['Itchy Yellow Crab Hat of Celebration', 20000000], ['Shaded Yellow Crab Hat of Celebration', 20444000], ['Shaded Yellow Crab Hat of Celebration', 25000000], ['Itchy Yellow Crab Hat of Celebration', 30000000], ['Yellow Crab Hat of Celebration', 30000000], ['Yellow Goblin Egg', 40000000], ['Neon Yellow Sheep Skin', 42000000], ['Neon Yellow Sheep Skin', 43000000], ['Neon Yellow Sheep Skin', 44000000], ['Neon Yellow Sheep Skin', 58000000], ['Neon Yellow Sheep Skin', 59700000], ['Unpleasant Yellow Crab Hat of Celebration', 75000000]]
    items2 = items
    for y in items2:
        for z in items2:
            if y[0] == z[0] and y[1] >= z[1]:
                print(y, y[1],z,z[1])
                items.remove(y)
                break
            continue
    print("/n")
    print(items2)
    print(items)
  • 1
    `items2 = items` won't create a copy of `items`. When you `items.remove(y)` you also remove it from `items2`. – Selcuk Sep 06 '21 at 02:46
  • (1) Lists in Python are passed by reference. Construct a new list if you want a deep(er) copy. (2) Please be more specific about what you are trying to achieve; “filter out items with the lowest values” is _not_ what your code does. (3) Your algorithm has a *cubic* (!) complexity (hint: the third dimension hides in `remove()`) for something that can be done in *linear* time. – Andrej Podzimek Sep 06 '21 at 02:57
  • For the record, [here’s a possible linear-time algorithm](https://pastebin.com/xxBPXd1i) if the goal was to remove _all_ items with the lowest value for each key — which is not entirely clear from the question. (The algorithm would require a _N_ * log _N_ time with tree-based containers, but sets and dicts use hash tables by default, so it’s linear.) – Andrej Podzimek Sep 06 '21 at 04:06
  • @AndrejPodzimek no. For starters, "pass by reference" refers to an evaluation strategy, i.e. how *how and when arguments to functions are evaluated*. This doesn't involve an argument to a function, and more importantly, Python **never** uses call by reference as an evaluation strategy, and the evaluation strategy is always the same regardless of the type of the objects involved. – juanpa.arrivillaga Sep 06 '21 at 05:47
  • @juanpa.arrivillaga Whatever Python’s nitty-gritty terminology might be, variables pointing at objects (no matter if they stem from function arguments or not) behave like references (by the C++ / Java meaning of the word). Here’s an unambiguous example: `f = lambda l: l.append(3); l = []; f(l); print(l);`. No matter what Python calls it, it prints `[3]`, which was the whole point. (And it also explains the consequences of `items2 = items`.) – Andrej Podzimek Sep 06 '21 at 12:52
  • @AndrejPodzimek yes, variables act like reference, but that isn't the same as call by reference. This isn't an issue of Python terminology, specifically. This is standard terminology. If you had call by reference, suppose you had a function, `def foo(&x): x = 1`, then `y = 0; foo(y); print(y)` would print `1` – juanpa.arrivillaga Sep 06 '21 at 18:30
  • @juanpa.arrivillaga But that is _exactly_ what happens for objects (e.g. lists), just without the `&` syntax. With `def foo(x): x[0] = 1`, this will print `1`: `y = [-1]; foo(y); print(y[0])`. In other words, objects are passed by reference in Python. Sure, there is no way to create references to “scalars” (`int` / `float` / `str`) (other than wrapping them in objects), but that was _not_ the topic of the question. The problem with the question was (among other things) the `items2 = items` assignment, which assigns a reference (to an object), not a copy. – Andrej Podzimek Sep 06 '21 at 19:17
  • @AndrejPodzimek "Objects are passed by reference" **everything is an object in Python**. Including `int` objects. And no, **python never uses pass by reference**. `x[0] = 1` is essentially syntactic sugar for a call to a mutator method, `x.__setitem__(0, 1)`. `int` objects are immutable, they lack mutator methods. Here, if you had call by reference, you could do: `def foo(&mylist): mylist = [1,2,3]` then `x = []; foo(x); print(x)` would print `[1, 2, 3]` But you can't, because Python *doesn't have call by reference*. This is just a *basic fact*. I don't know why you insist differently – juanpa.arrivillaga Sep 06 '21 at 19:47
  • @juanpa.arrivillaga The fact remains that the example mentioned above prints `1` and not `-1`. So, Python “insists otherwise”, not me. – Andrej Podzimek Sep 06 '21 at 20:25
  • @AndrejPodzimek Your example is *totally irrelevant*. You can do the same thing in C with pointers to structs, and *C is definitely call by value always*. It doesn't address the issue of *call by reference at all*. Look, I don't know what point you think you are making, because fundamentally, you have a misapprehension about the definition of *call by reference*. This is just an issue of the definitions of terminology. – juanpa.arrivillaga Sep 06 '21 at 20:31
  • @juanpa.arrivillaga Indeed, this is an issue of terminology — and perhaps we can agree to differ on terminology without reaching for words like “misapprehension”. Again, my goal was to explain the effect of `items2 = items`, _not_ to delve into (convoluted) Python-specific terminology. For example, even though “everything is an object”, because `x = 5; y = 5; print(x is y)` says `True`, both `x` and `y` are *“references to an immutable, implicitly existing singleton”* — which yields (disregarding the “philosophy” behind it) a behavior equivalent to a “scalar” type. – Andrej Podzimek Sep 06 '21 at 21:13

1 Answers1

2

items2 = items does not create copy of the list, but only a reference to it. you probably want to use items2 = items[:]

John
  • 36
  • 1