PYTHON List manipulation

I have two lists which represent the order items deleted and order items added during a customer order review process. Note that orders are reviewed by quarter, so its possible for an item to be dropped from Q1 and re-ordered in Q3 and maybe also in Q2. This is why you can see in the example below item 9 in the dropped list and item 9 occurring 3 times in the added list.

For Example

dropped = [8, 3, 10, 1, 5, 9]
added = [1, 5, 20, 9, 14, 9, 9]

I need to rationalize the above lists into NET lists - where the same number cannot appear in both dropped and added lists.

net_dropped = [8, 3, 10]
net_added = [20, 14, 9, 9]  ..... notice how there are two 9's remaining out of the original 3.

My best shot at achieving this  :
----------------------------------------------------------------------------
net_dropped = [x for x in dropped if not x in added]
net_added =[x for x in added if not x in dropped]
-------------------------------------------------------------------------

which does not work because the ALL of the 9's are deleted from the added list.

The added and deleted lists can vary in relative size and can even be blank ... [ ]

Can someone help me with a solution.  

thanks, james
jameskaneAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

gelonidaCommented:
Are the lists big?
Does the solution have to be efficient?

This might work, though a little manual. As I didn't know I tried to preserve the order.

from collections import Counter # for python 2.7 or newer

dropped = [8, 3, 10, 1, 5, 9]
added = [1, 5, 20, 9, 14, 9, 9]

add_cnt = Counter(added)
new_dropped = []
for value in dropped:
    in_add_cnt = add_cnt.get(value, 0)
    if in_add_cnt:
        added.remove(value) $ preserves the order, but is a little costly
        add_cnt[value] -= 1
    else:
        new_dropped.append(value)
dropped =  new_dropped

Open in new window

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Walter RitzelSenior Software EngineerCommented:
on your net added, use net dropped instead of dropped.
jameskaneAuthor Commented:
Thanks for the replies gelonida and  Walter


gelonida,
This runs and gives the net version of dropped. However,  I would still need the corresponding net version for
added. No problem with efficiency - the lists could be around 20 items. However either one of added or dropped could be an empty list.
dropped = [8, 3, 10, 1, 5, 9]
added = [1, 5, 20, 9, 14, 9, 9]
import collections
add_cnt = collections.Counter(added)
new_dropped = []
for value in dropped:
    in_add_cnt = add_cnt.get(value, 0)
    if in_add_cnt:
        added.remove(value) # preserves the order, but is a little costly
        add_cnt[value] -= 1
    else:
        new_dropped.append(value)
dropped =  new_dropped

Walter I tried your suggestion -

dropped = [8, 3, 10, 1, 5, 9]
added = [1, 5, 20, 9, 14, 9, 9]

net_dropped = [x for x in dropped if not x in added]
net_added =[x for x in added if not x in net_dropped]      
print(net_dropped, "final_added")
print(net_added, "final_dropped")
print(dropped)

However, while the result for dropped is correct - the list added remains unchanged. Items 1, 5, 9 should have been removed

Thanks again to you both

james
jameskaneAuthor Commented:
gelonida,

just re-ran your template for added and it works on the example.  Also ran it for an example with an empty list and it works. The counter is a very helpful aspect - as below,  the line
collections.Counter(added)  evaluates to  Counter({9: 3, 1: 1, 20: 1, 5: 1, 14: 1}). Probably silly question, how  can I get this to evaluate / or modify it to read  ({9: 3, 1: 1, 20: 1, 5: 1, 14: 1})....ie loose the Counter add on ?

dropped = [8, 3, 10, 1, 5, 9]
added = [1, 5, 20, 9, 14, 9, 9]
import collections
drop_cnt = collections.Counter(dropped)
new_added = []
for value in added:
    in_drop_cnt = drop_cnt.get(value, 0)
    if in_drop_cnt:
        dropped.remove(value) # preserves the order, but is a little costly
        drop_cnt[value] -= 1
    else:
        new_added.append(value)
added =  new_added
add_cnt = collections.Counter(added)
print(added, add_cnt)
gelonidaCommented:
just typecast counter to a dict:

add_cnt_as_ordinary_dict = dict(add_cnt)
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Python

From novice to tech pro — start learning today.