solving problems for lists in python - python

How to write a code which takes two lists as input and returns multiplication for the lists
e.g Result should look like this.
First-list [1,2]
Second-list [2,1]
Your result [2,1,4,2]
I have tried with the code
list1=[1,2]
list2=[2,1]
list3=list1*list2

First-list =[1,2]
Second-list=[2,1]

Couldn't find a duplicate (I'll delete if anyone does)
You can use a list comprehension
>>> a = [1, 2]
>>> b = [2, 1]
>>> [x * y for x in a for y in b]
[2, 1, 4, 2]

Related

Filter nested list with list comprehension based on other list in python

I have two lists like this:
a = [[1,2,3],[2,3,4],[5,6,7],[7,8,9]]
b = [1,2]
I would now like to filter list a, to keep only the items which contain the items in list b. So the desired output would look like this:
[[1,2,3],[2,3,4]]
I have tried some nested list comprehensions, which I could think of, but could not get the desired output. Any advice is appreciated.
you could try something like this :
print([i for i in a if any(map(i.__contains__,b))])
>>> [[1, 2, 3], [2, 3, 4]]
I would try something like this:
a = [[1,2,3],[2,3,4],[5,6,7],[7,8,9]]
b = [1,2]
result = [lst for lst in a if any(x in lst for x in b)]
A combination of list comprehension and sets would yield the wanted result. Note; I assume that repeated items and ordering is not of interest, if this is the case - a set won't work since it ignores ordering and only allows unique items.
A simple list comprehension would do, like below
filter_items = set(filter_items)
[sublist for sublist in original_list if not set(sublist).isdisjoint(filter_items)]
There's mainly one interesting part of this list comprehension, namely the if not set(sublist).isdisjoint(filter_items). Here you only keep the sublist if the set of sublist is not disjoint of the set filter_items i.e. none of the filter_items is in the sublist.
for your given example the provided answer would yield the following:
>>> a = [[1,2,3],[2,3,4],[5,6,7],[7,8,9]]
>>> b = set([1,2])
>>> [sublist for sublist in a if not set(sublist).isdisjoint(b)]
[[1, 2, 3], [2, 3, 4]]
Using a set approach the in can be mimic with an intersection:
a = [[1,2,3],[2,3,4],[5,6,7],[7,8,9]]
b = [1,2]
b_as_set = set(b)
out = [l for l in a if b_as_set.intersection(l)]
# [[1, 2, 3], [2, 3, 4]]
I would try something like this.
a = [[1,2,3],[2,3,4],[5,6,7],[7,8,9]]
b = [1,2]
print([lst for lst in a if any([item in b for item in lst])])

Compare lists in the same dictionary of lists

In resume, I have two keys in the same dictionary where each one has their corresponding lists.
I try to compare both list to check common and differential elements. It means that the output I will count how many elements are identical or present in only one key's list.
from the beginning I am inserting the elements using the files as arguments and they are read in the function
def shared(list):
dict_shared = {}
for i in list:
infile = open(i, 'r')
if i not in dict_shared:
dict_shared[i] = []
for line in infile:
dict_shared[spacer].append(record.id)
return dict_shared
Now I am stuck trying to find a way to compare the lists created and present in the dictionary.
dict = {a:[1,2,3,4,5], b:[2,3,4,6]}
My intention is to compare the lists in order to have the lines shared between two texts.
a: [1,5]
b: [6]
a-b: [2,3,4]
From now I can't find a way to solve this. Any suggestion?
You could use set:
d = {'a':[1,2,3,4,5], 'b':[2,3,4,6]}
print(list(set(d['a'])-set(d['b'])))
print(list(set(d['b'])-set(d['a'])))
print(list(set(d['b'])&set(d['a'])))
result:
[1, 5]
[6]
[2, 3, 4]
you can do that by utilising python inbuilt functions like union, difference, intersection.
Note: These are for sets,
you can convert a list to set by
1stset = set(a)
example:
print(1stset.difference(2ndset))
print(1stset.intersection(2ndset))
print(1stset.union(2ndset))
you can refer the following links for more information
https://www.geeksforgeeks.org/python-intersection-two-lists/
https://www.geeksforgeeks.org/python-union-two-lists/
https://www.geeksforgeeks.org/python-difference-two-lists/
A solution with list comprehension would be:
dictionary = {'a':[1,2,3,4,5], 'b':[2,3,4,6]}
only_in_a = [x for x in dictionary['a'] if not x in dictionary['b']]
only_in_b = [x for x in dictionary['b'] if not x in dictionary['a']]
in_both = [x for x in dictionary['a'] if x in dictionary['b']]
Note that this is not especially wise in terms of complexity, for larger lists.
Not sure if I understand correctly what you are trying to achieve but it seems like you'd need set operations:
dictionary = {"a":[1,2,3,4,5], "b":[2,3,4,6]}
#in a but not in b
set(dictionary["a"]) - set(dictionary["b"])
#in b but not in a
set(dictionary["b"]) - set(dictionary["a"])
#union of both
set(dictionary["b"]).union(set(dictionary["a"]))
#intersection of both
set(dictionary["b"]).intersection(set(dictionary["a"]))
You can try something like this
mydict = {'a': [1,2,3,4,5], 'b': [2,3,4,6]}
>>> list(set(mydict['a']).intersection(mydict['b'])) # common to both
[2, 3, 4]
>>> list(set(mydict['a']).difference(mydict['b'])) # a - b
[1, 5]
>>> list(set(mydict['b']).difference(mydict['a'])) # b - a
[6]
>>> list(set(mydict['a']).union(mydict['b'])) # union of both
[1, 2, 3, 4, 5, 6]
Try this
print("a - b : {} ".format(list(set(_dict['a']) - set(_dict['b']))))
print('b - a : {} '.format(list(set(_dict['b']) - set(_dict['a']))))
print('a \u2229 b : {} '.format(list(set(_dict['a']).intersection(set(_dict['b'])))))
Output
a - b : [1, 5]
b - a : [6]
a ∩ b : [2, 3, 4]

Python list comprehension and do action

Is it possible to do an action with the item in a list comprehension?
Example:
list = [1, 2, 3]
list_filtered = [ i for i in list if i == 3 AND DO SOMETHING WITH I]
print (list_filtered)
For example if I want to remove the '3' how would I go about it? Logic says that it's something like:
list = [1, 2, 3]
list_filtered = [ i for i in list if i == 3 && list.remove(i) ]
print (list_filtered)
I can't seem to make Python perform an action with that 'i' with any syntax that I tried. Can someone please elaborate?
EDIT: Sorry, the explanation might not be clear enough. I know how to iterate and create the new list. I want to create "list_filtered" and remove that value from "list" if it fits the "IF" statement.
Practically I need the following:
list = [1, 2, 3]
list_filtered = [ i for i in list if i == 3 && list.remove(i) ]
print (list_filtered)
# output >> [3]
print (list)
# output >> [1, 2]
I hope the above makes it more clear. Also, please note that my question is if this can be done in the list comprehension specifically. I know how to do it with additional code. :)
EDIT2: Apparently what I wanted to do isn't possible and also isn't advisable (which is the reason it isn't possible). It seemed like a logical thing that I just didn't know how to do. Thanks guys :)
If you're just trying to remove 3 you could do:
list_filtered=[i for i in list if i != 3]
print(list_filtered) # [1,2]
This will remove all values that are not equal to 3.
Alternatively if you wanted to do something like increment all the items in the list you would do:
[i+1 for i in list]
>>> [2,3,4]
Using a function on every item of the list would look like:
[float(i) for i in list]
>>> [1.0, 2.0, 3.0]
You can do ternary statements:
[i if i<3 else None for i in list]
>>>[1, 2, None]
and a whole lot more...
Here is more documentation on list comprehensions.
Given your new updates, I would try something like:
list_filtered=[list.pop(list.index(3))]
Then list_filtered would be [3] and list would be [1,2] as your specified.
Your miss understand the purpose of list comprehension. List comprehension should be used to create a list, not to use its side effects. Further more, as Leijot has already mentioned, you should never modify a container while iterating over it.
If you want to filter out certain elements in a list using list comprehension, use an if statement:
>>> l = [1, 2, 3]
>>> l_filtered = [i for i in l if i != 3]
>>> l_filtered
[1, 2]
>>>
Alternatively, you can use the builtin function filter():
>>> l = [1, 2, 3]
>>> l_filtered = list(filter(lambda x: x != 3, l))
>>> l_filtered
[1, 2]
>>>
Edit: Based on your most recent edit, what your asking is absolutely possible. Just use two different list comprehensions:
>>> l = [1, 2, 3]
>>> l_filtered = [i for i in l if i == 3]
>>> l_filtered
[3]
>>> l = [i for i in l if i != 3] # reassigning the value of l to a new list
>>> l
[1, 2]
>>>
Maybe you want to provide a different example of what you're trying to do since you shouldn't remove elements from a list while you're iterating over it. Since list comprehensions create another list anyway, you could accomplish the same thing as your example by building a list that omits certain elements. If your goal is to create a list that excludes the value 3, to slightly modify your example:
l = [1, 2, 3]
list_filtered = [ i for i in l if i != 3 ]
l remains unaltered, but list_filtered now contains [1, 2].

Remove duplicates from list, including original matching item

I tried searching and couldn't find this exact situation, so apologies if it exists already.
I'm trying to remove duplicates from a list as well as the original item I'm searching for. If I have this:
ls = [1, 2, 3, 3]
I want to end up with this:
ls = [1, 2]
I know that using set will remove duplicates like this:
print set(ls) # set([1, 2, 3])
But it still retains that 3 element which I want removed. I'm wondering if there's a way to remove the duplicates and original matching items too.
Use a list comprehension and list.count:
>>> ls = [1, 2, 3, 3]
>>> [x for x in ls if ls.count(x) == 1]
[1, 2]
>>>
Here is a reference on both of those.
Edit:
#Anonymous made a good point below. The above solution is perfect for small lists but may become slow with larger ones.
For large lists, you can do this instead:
>>> from collections import Counter
>>> ls = [1, 2, 3, 3]
>>> c = Counter(ls)
>>> [x for x in ls if c[x] == 1]
[1, 2]
>>>
Here is a reference on collections.Counter.
If items are contigious, then you can use groupby which saves building an auxillary data structure in memory...:
from itertools import groupby, islice
data = [1, 2, 3, 3]
# could also use `sorted(data)` if need be...
new = [k for k, g in groupby(data) if len(list(islice(g, 2))) == 1]
# [1, 2]

Indexing a nested list in python

Given data as
data = [ [0, 1], [2,3] ]
I want to index all first elements in the lists inside the list of lists. i.e. I need to index 0 and 2.
I have tried
print data[:][0]
but it output the complete first list .i.e.
[0,1]
Even
print data[0][:]
produces the same result.
My question is specifically how to accomplish what I have mentioned. And more generally, how is python handling double/nested lists?
Using list comprehension:
>>> data = [[0, 1], [2,3]]
>>> [lst[0] for lst in data]
[0, 2]
>>> [first for first, second in data]
[0, 2]
Using map:
>>> map(lambda lst: lst[0], data)
[0, 2]
Using map with operator.itemgetter:
>>> import operator
>>> map(operator.itemgetter(0), data)
[0, 2]
Using zip:
>>> zip(*data)[0]
(0, 2)
With this sort of thing, I generally recommend numpy:
>>> data = np.array([ [0, 1], [2,3] ])
>>> data[:,0]
array([0, 2])
As far as how python is handling it in your case:
data[:][0]
Makes a copy of the entire list and then takes the first element (which is the first sublist).
data[0][:]
takes the first sublist and then copies it.
The list indexing or nesting in general (be it dict, list or any other iterable) works Left to Right. Thus,
data[:][0]
would work out as
(data[:]) [0] == ([[0, 1], [2,3]]) [0]
which ultimately gives you
[0, 1]
As for possible workaronds or proper methods, falsetru & mgilson have done a good job in that regards.
try this:
print [x for x, y in data[:]]

Categories