Compare two list of dictionaries and get difference - python

I am new to python. In Python, I want to compare two list of dictionaries
Below are 2 list of dictionary I want to compare based on key which is "zrepcode" and id which is the number "1", "3", and "4"...
Code snippet is as follows:
List
1 = [{"3":[{"period":"P13","value":10,"year":2022}],"zrepcode":"55"},{"1":[{"period":"P10","value":5,"year":2023}],"zrepcode":"55"}]
List2 = [{"1":[{"period":"P1","value":10,"year":2023},{"period":"P2","value":5,"year":2023}],"zrepcode":"55"},{"3":[{"period":"P1","value":4,"year":2023},{"period":"P2","value":7,"year":2023}],"zrepcode":"55"},{"4":[{"period":"P1","value":10,"year":2023}],"zrepcode":"55"}]
After Comparision, we need the unique list of dictionary from list2.
res = [{"4":[{"period":"P1","value":10,"year":2023}],"zrepcode":"55"}]
This is the expected output, Now I don't know how I get this.

Here is my solution:
list_1 = [
{"3":[{"period":"P13","value":10,"year":2022}],"zrepcode":"55"},
{"1":[{"period":"P10","value":5,"year":2023}],"zrepcode":"55"}
]
list_2 = [
{"1":[{"period":"P1","value":10,"year":2023},{"period":"P2","value":5,"year":2023}],"zrepcode":"55"},
{"3":[{"period":"P1","value":4,"year":2023},{"period":"P2","value":7,"year":2023}],"zrepcode":"55"},
{"4":[{"period":"P1","value":10,"year":2023}],"zrepcode":"55"}]
list_1_keys = [sorted(element.keys())[0] for element in list_1]
res = [element for element in list_2 if sorted(element.keys())[0] not in list_1_keys]
I think you do not need any check on the key zrepcode because this is always the same.
let's me know if you need more explanation/details about the solution.
I hope it will help you.
EDIT
here is the solution if we take into account the zrepcode
list_1_couple = []
for element in list_1:
keys = sorted(element.keys())
list_1_couple.append([keys[0], element[keys[1]]])
res = []
for element in list_2:
keys = sorted(element.keys())
if [keys[0], element[keys[1]]] not in list_1_couple:
res.append(element)
print(res)
You can probably clean a bit the code, but at least it should works 😉
EDIT 2
If you prefer to use some one-liner
list_1_couple = [[sorted(element.keys())[0], element[sorted(element.keys())[1]]] for element in list_1 ]
res = [element for element in list_2 if [sorted(element.keys())[0], element[sorted(element.keys())[1]]] not in list_1_couple]
will do the trick too

Related

how to slice strings with the help of a list of tuples?

I have a list of tuples as as follows:
list_1 = [(2,10), (3,13), (5,23)]
and also a list of strings as follows:
list_2 = [ATGCATGCGAGTGCGAGTGCGTGCGTGCAGTGCGAGTGC,
ATCGTCGTCGACGTAGCTAGCTAGCTAGCTAGCTAS,
ATGCGTACGATCGATCGATCGATCGATCGAGCTAGCTAGCT]
I want to slice the list of strings with the help of given tuple integer gaps.
For example;
I want to slice the first string from indexes 2 and 10 and print out only the letters which belong to those indexes. So the result print will be as ‘GCATGCGAG’.
For the second string it should slice and select the indexes from 3-13.so the result should be ‘GTCGTCGACGTAG’.
This should go on.
Can somebody suggest me a code for this.
Thanks in advance.
A straightforward solution is to zip the two lists and use tuple elements from one list as slice parameters for the other:
[l2[l1[0] : l1[1] + 1] for l1, l2 in zip(list_1, list_2)]
#['GCATGCGAG', 'GTCGTCGACGT', 'TACGATCGATCGATCGATC']
If the second element of a tuple were the next element after the end of the subsequence (which is a "normal" Python convention), you could get an even more elegant solution:
[l2[slice(*l1)] for l1, l2 in zip(list_1, list_2)]
#['GCATGCGA', 'GTCGTCGACG', 'TACGATCGATCGATCGAT']
You can use the function map:
list_1 = [(2,10), (3,13), (5,23)]
list_2 = ['ATGCATGCGAGTGCGAGTGCGTGCGTGCAGTGCGAGTGC',
'ATCGTCGTCGACGTAGCTAGCTAGCTAGCTAGCTAS',
'ATGCGTACGATCGATCGATCGATCGATCGAGCTAGCTAGCT']
list(map(lambda idx, lst: lst[idx[0]: idx[1]+1], list_1, list_2))
# ['GCATGCGAG', 'GTCGTCGACGT', 'TACGATCGATCGATCGATC']
use it to do what you want: string[num1:num2]
To print them all, you need this:
for i in range(len(list_1)):
print(list_2[i][list_1[i][0]:list_1[i][1] +1])
hopefully the problem is solved,
Have a Good Code :)
You can use list comprehension to achieve this :
list_3 = [item[list_1[int(index)][0]:list_1[int(index)][1]] for index,item in enumerate(list_2)]
Above code will take one element from list_2 to item and use it index and use that in list_1 and than slice item according to tuple of list_1.
How it work :
Take item one by one from list_2
take tuple from list_1 using index
slice item using tuple
store it in list_3

Relationship between elements of two list: how to exploit it in Python?

SO here is my minimal working example:
# I have a list
list1 = [1,2,3,4]
#I do some operation on the elements of the list
list2 = [2**j for j in list1]
# Then I want to have these items all shuffled around, so for instance
list2 = np.random.permutation(list2)
#Now here is my problem: I want to understand which element of the new list2 came from which element of list1. I am looking for something like this:
list1.index(something)
# Basically given an element of list2, I want to understand from where it came from, in list1. I really cant think of a simple way of doing this, but there must be an easy way!
Can you please suggest me an easy solution? This is a minimal working example,however the main point is that I have a list, I do some operation on the elements and assign these to a new list. And then the items get all shuffled around and I need to understand where they came from.
enumerate, like everyone said is the best option but there is an alternative if you know the mapping relation. You can write a function that does the opposite of the mapping relation. (eg. decodes if the original function encodes.)
Then you use decoded_list = map(decode_function,encoded_list) to get a new list. Then by cross comparing this list with the original list, you can achieve your goal.
Enumerate is better if you are certain that the same list was modified using the encode_function from within the code to get the encoded list.
However, if you are importing this new list from elsewhere, eg. from a table on a website, my approach is the way to go.
You could use a permutation list/index :
# I have a list
list1 = [1,2,3,4]
#I do some operation on the elements of the list
list2 = [2**j for j in list1]
# Then I want to have these items all shuffled around, so for instance
index_list = range(len(list2))
index_list = np.random.permutation(index_list)
list3 = [list2[i] for i in index_list]
then,with input_element:
answer = index_list[list3.index(input_element)]
Based on your code:
# I have a list
list1 = [1,2,3,4]
#I do some operation on the elements of the list
list2 = [2**j for j in list1]
# made a recode of index and value
index_list2 = list(enumerate(list2))
# Then I want to have these items all shuffled around, so for instance
index_list3 = np.random.permutation(index_list2)
idx, list3 = zip(*index_list3)
#get the index of element_input in list3, then get the value of the index in idx, that should be the answer you want.
answer = idx[list3.index(element_input)]
def index3_to_1(index):
y = list3[index]
x = np.log(y)/np.log(2) # inverse y=f(x) for your operation
return list1.index(x)
This supposes that the operations you are doing on list2 are reversible. Also, it supposes that each element in list1 is unique.

Sort list based on pattern

I'd like to know how I can easily generate a list based on the values/order of two other lists:
list_a = ['web1','web2','web3','web1','web4']
list_b = ['web2','web4','web1','web5','web1']
I'd like to retrieve the "list_b" list ordered by value from "list_a":
final = ['web1','web2','web1','web4','web5']
If an entry exist on list_b but not on list_a, then the value is appended to the list at the end.
I'm not sure where to start, my initial thinking was to retrieve all the indexes with enum [i for i, x in enumerate(mylist) if x==value], then sort the list, but I'm having hard time managing entries with multiples index (eg: web1) . Just wondering if you guys are thinking about an easy way to achieve this ?
An extremely simplistic way would be to just iterate over list_a, and should you find each element in list_b you remove it and append it to a list. Then after iterating all that remains in list_b are the elements that you need to add to the end of your list.
list_a = ['web1','web2','web3','web1','web4']
list_b = ['web2','web4','web1','web5','web1']
front = []
for ele in list_a:
if ele in list_b:
front.append(ele)
list_b.remove(ele)
final = front + list_b
print(final)
Outputs:
['web1', 'web2', 'web1', 'web4', 'web5']
Another trickier way would be to use collections.Counter and a few list comprehensions, leveraging the set intersection and difference of the counters.
from collections import Counter
cnt_a, cnt_b = Counter(list_a), Counter(list_b)
intersct = (cnt_a & cnt_b)
diff = (cnt_b - cnt_a)
final = [a for a in list_a if a in intersct] + [b for b in list_b if b in diff]

Generate all combinations from multiple lists with repeat lists

I have multiple lists, some of them are repeats and I need all combinations, excluding ones where the same element from a repeated list is chosen. For example, I have
import itertools
list1 = [1,2,3]
list2 = [4,5,6]
list3 = [4,5,6]
list4 = [7,8,9]
a = [list1,list2,list3,list4]
print list(itertools.product(*a))
which outputs
(1,4,4,7)
(1,4,4,8)
(1,4,4,9)
(1,4,5,7)
.
.
.
etc, as you'd expect, but what I want it to do is output every combination, without repeating elements from lists 2 and 3. Like this:
(1,4,5,7)
(1,4,5,8)
(1,4,5,9)
(1,4,6,7)
(1,4,6,8)
(1,4,6,9)
(1,5,6,7)
(1,5,6,8)
(1,5,6,9)
(2,4,5,7)
.
.
.
I'd obviously like to avoid having to remove them manually after creating the list, but any help on how to do this efficiently is really appreciated. Thanks.
The easy way is a generator expression with a filter:
print list(item for item in itertools.product(*a) if item[1] != item[2])
If two items are considered the same if they contain the same elements, and if each item is guaranteed to contain no repeated elements, you can discard duplicates by changing them into sets and only adding them to your list if they're not already in it:
result = []
for item in itertools.product(*a):
if item[1]==item[2]:
continue
item = set(item)
if item not in result:
result.append(item)
print result

How can I check if a list exist in a dictionary of lists in the same order

Say I have a dictionary of lists,
C = {}
li = []
li.append(x)
C[ind] = li
And I want to check if another list is a member of this dictionary.
for s in C.values():
s.append(w)
Python checks it for any occurrences of the values in s and the dictionary values. But I want to check if any of the lists in the dictionary is identical to the given list.
How can I do it?
Use any for a list of lists:
d = {1 : [1,2,3], 2: [2,1]}
lsts = [[1,2],[2,1]]
print(any(x in d.values() for x in lsts))
True
d = {1:[1,2,3],2:[1,2]}
lsts = [[3,2,1],[2,1]]
print(any(x in d.values() for x in lsts))
False
Or in for a single list:
lst = [1,2]
lst in d.itervalues()
Python will compare each element of both lists so they will have to have the same order to be equal, even if they have the same elements inside the order must also be the same so a simple comparison will do what you want.
in does the trick perfectly, because it does a comparison with each element behind the scenes, so it works even for mutable elements:
lst in d.values()

Categories

Resources