a = [2,7,9]
b = [[7,9],[1,2],[2,9]]
How many pairs in list [a] matches pair tuple [b]
Notice both pair [7,9] and [2,9] in list [a]. Even though pair [1,2] contains a digit of 2, it doesn't get counted because both digits are not in list [a].
The return value should be 2, the len of the matching pairs.
len(filter(lambda l:if_in(b,l),a))
Need help creating a if_in function or a simpler way of writing this function all in one. How can I make this function work no matter the size of a or b.
Make a a set and use set.issuperset, checking if a is a superset of each sublist:
a = [2,7,9]
b = [[7,9],[1,2],[2,9]]
st = set(a)
print(sum(st.issuperset(sub) for sub in b))
2
You can go two ways, either making all the sublists sets or as above just make a set, when a is a superset of a sublist then the sublist is a subset of a:
In [6]: a = [2,7,9]
In [7]: b = [[7,9],[1,2],[2,9]]
In [8]: st = set(b[0])
In [9]: st.issubset(a)
Out[9]: True
In [10]: st = set(b[1])
In [11]: st.issubset(a)
Out[11]: False
In [13]: st = set(a)
In [13]: st.issuperset(b[0])
Out[13]: True
In [14]: st.issuperset(b[1])
Out[14]: False
Obviously as there are only a few numbers in your a list it make more sense to make a set from a and use superset.
If you want to work with the subsets of a, you can use itertools.combinations(iterable, r).
Quoting the docs, returns r length subsequences of elements from the input iterable.
from itertools import combinations
a = [2, 7, 9]
b = [(7, 9), (1, 2), (2, 9)]
# combinations returns a collection of tuples
# so changed your b items to tuples.
len(filter(lambda x: x in b, combinations(a ,2))
Related
I am quite new to Sympy (running with Python 3).
Given two lists of integers, in general not of equal lengths and whose elements might repeat, I need to eliminate all pairs of equal elements between the two lists.
For example, given
List_a=[1, 2, 3, 4, 4], List_b=[0, 2, 2, 4]
I shall eliminate the pairs (2,2) and (4,4) and output
List_ar=[1,3,4], List_br=[0,2]
If the two lists are equal I shall get two empty lists as output.
I have been trying to compare the lists element by element ( "for" and "while" loops) and when found equal to delete the pair from both lists. Upon that to repeat the procedure on the reduced lists till no deletion is made.
But lacking of a "goto" control I do not know how to handle the variable length lists.
Thanks for helping.
I you convert them to multiset you can compare the counts of common keys:
>>> from sympy.utilities.iterables import multiset
>>> ma = multiset(lista)
>>> mb = multiset(listb)
>>> for k in set(ma) & set(mb):
... n = min(ma[k],mb[k])
... ma[k] -= n
... mb[k] -= n
...
>>> lista = [i for k in ma for i in [k]*ma[k]]
>>> listb = [i for k in mb for i in [k]*mb[k]]
You could also treat this like a merge sort but the above is direct.
A general Python solution:
def g(a, b):
def ensure2(xs):
ys = [list(x) for x in xs]
if ys == []:
return [[], []]
else:
return ys
n = min(len(a), len(b))
c, d = ensure2(
zip(*
filter(lambda x: x[0] != x[1],
zip(a, b))))
return c + a[n:], d + b[n:]
a = [1,2,3,4,4]
b = [0,2,2,4]
c = [0,2,2,4]
d = []
# two different lists
ar, br = g(a, b)
print(ar) # [1, 3, 4]
print(br) # [0, 2]
# two identical lists
br, cr = g(b, c)
print(br) # []
print(cr) # []
# one empty list
ar, dr = g(a, d)
print(ar) # [1, 2, 3, 4, 4]
print(dr) # []
Use zip() to create the pairs
Use filter() to remove pairs with equal elements
Use zip(*...) to split the remaining pairs back to two lists
Use ensure2() to guard against empty lists
Use + list[n:] to append excessive elements back to the originally longer list
Example, I have the following lists in Python
A = [1,2,3]
B = [4,5,6]
I would need to create a new list C such that the elements should be paired as a separate lists based on their index numbers. i.e., C = [[[1,4],[2,5],[3,6]], [[1,4],[2,5],[3,6]]]
I have written a code to that but it is purely structured. Can you please provide if there is any better way other than the below code?
A = [1,2,3]
B = [4,5,6]
D = [a,b,c]
E = [d,e,f]
C = []
list = []
for i in range(len(A)):
list.append([A[i],B[i]])
C.append(list)
list = []
for i in range(len(D)):
list.append([D[i],E[i]])
C.append(list)
I have to repeat this code if I have multiple cases similar to the above one in my code. Which is poor in structuring.
Can someone suggest any better method for the problem?
You can use zip, convert that to list
list(zip(a,b))
which will give list of tuples. If you want list of lists, you can go:
[[i,j] for i,j in zip(a,b)]
You can try something like this in one line.
C = [[A[i],B[i]] for i in range(len(A))]
Be careful if A and B don't have the same length though!
Your problem has a simple solution found in Python's built-in functions,
The 'zip' function takes 2 arguments (iterables) and return a single iterator.
Here is an example code:
a = [1, 2, 3]
b = [4, 5, 6]
c = list(zip(a, b))
# c -> [(1, 4), (2, 5), (3, 6)]
# if you want the elements to be list instead of tuple you can do
c = [[i, j] for i,j in zip(a, b)]
# c -> [[1, 4], [2, 5], [3, 6]]
you can use zip for this
c= zip(a,b)
c=list(c)
if you convert in set then
c=set(c)
Using numpy, the following would be efficient.
import numpy as np
A = [1,2,3]
B = [4,5,6]
a = np.array(A)
b = np.array(B)
c = np.vstack((a, b)).T
print c
C = c.tolist()
print C
lower case letters are all numpy arrays, upper case are python arrays
I am new to Python.
I have a tuple
Tuple=(3,4,5)
I have a list.
List=[3,5]
I want the output to be 4 since [3,5] is present in (3,4,5)
How do I do this using Python?
You can convert your iterables to a set and then perform set difference.
In [459]: t = (3,4,5)
In [460]: l = [3,5]
In [461]: set(t) - set(l) if all(x in t for x in l) else None
Out[461]: {4}
my_tuple = (3, 4, 5)
my_list = [3, 5]
# Check to see whether each item in your list is also in the tuple.
if all(item in my_tuple for item in my_list):
# Convert both to sets and print the difference.
print set(my_tuple) - set(my_list)
Output:
set([4])
Sometime I write code like this:
a,temp,b = s.partition('-')
I just need to pick the first and 3rd elements. temp would never be used. Is there a better way to do this?
In other terms, is there a better way to pick distinct elements to make a new list?
For example, I want to make a new list using the elements 0,1,3,7 from the old list. The
code would be like this:
newlist = [oldlist[0],oldlist[1],oldlist[3],oldlist[7]]
It's pretty ugly, isn't it?
Be careful using
a, _, b = s.partition('-')
sometimes _ is use for internationalization (gettext), so you wouldn't want to accidentally overwrite it.
Usually I would do this for partition rather than creating a variable I don't need
a, b = s.partition('-')[::2]
and this in the general case
from operator import itemgetter
ig0137 = itemgetter(0, 1, 3, 7)
newlist = ig0137(oldlist)
The itemgetter is more efficient than a list comprehension if you are using it in a loop
For the first there's also this alternative:
a, b = s.partition('-')[::2]
For the latter, since there's no clear interval there is no way to do it too clean. But this might suit your needs:
newlist = [oldlist[k] for k in (0, 1, 3, 7)]
You can use Python's extended slicing feature to access a list periodically:
>>> a = range(10)
>>> # Pick every other element in a starting from a[1]
>>> b = a[1::2]
>>> print b
>>> [1, 3, 5, 7, 9]
Negative indexing works as you'd expect:
>>> c = a[-1::-2]
>>> print c
>>> [9, 7, 5, 3, 1]
For your case,
>>> a, b = s.partition('-')[::2]
the common practice in Python to pick 1st and 3rd values is:
a, _, b = s.partition('-')
And to pick specified elements in a list you can do :
newlist = [oldlist[k] for k in (0, 1, 3, 7)]
If you don't need to retain the middle field you can use split (and similarly rsplit) with the optional maxsplit parameter to limit the splits to the first (or last) match of the separator:
a, b = s.split('-', 1)
This avoids a throwaway temporary or additional slicing.
The only caveat is that with split, unlike partition, the original string is returned if the separator is not found. The attempt to unpack will fail as a result. The partition method always returns a 3-tuple.
Does a direct way to do this exists?
if element in aList:
#get the element from the list
I'm thinking something like this:
aList = [ ([1,2,3],4) , ([5,6,7],8) ]
element = [5,6,7]
if element in aList
#print the 8
L = [([1, 2, 3], 4), ([5, 6, 7], 8)]
element = [5, 6, 7]
for a, b in L:
if a == element:
print b
break
else:
print "not found"
But it sounds like you want to use a dictionary:
L = [([1, 2, 3], 4), ([5, 6, 7], 8)]
element = [5, 6, 7]
D = dict((tuple(a), b) for a, b in L)
# keys must be hashable: list is not, but tuple is
# or you could just build the dict directly:
#D = {(1,2,3): 4, (5,6,7): 8}
v = D.get(tuple(element))
if v is not None:
print v
else:
print "not found"
Note that while there are more compact forms using next below, I imagined the reality of your code (rather than the contrived example) to be doing something at least slightly more complicated, so that using an block for the if and else becomes more readable with multiple statements.
(Note: this answer refers to the question text, not the example given in the code, which doesn't quite match.)
Printing the element itself doesn't make any sense, because you already have it in the test:
if element in lst:
print element
If you want the index, there's an index method:
if element in lst:
print lst.index(element)
And, on the off chance that you're asking this because you want to loop through a list and do things with both the value and the index, be sure to use the enumerate idiom:
for i, val in enumerate(lst):
print "list index": i
print "corresponding value": val
>>> aList = [ ([1,2,3],4) , ([5,6,7],8) ]
>>> element = [5,6,7]
if you only wish to check if the first element is present
>>> any(element==x[0] for x in aList)
True
to find the corresponding value
>>> next(x[1] for x in aList if element==x[0])
8
>>> aList = [ ([1,2,3],4) , ([5,6,7],8) ]
>>> for i in aList:
... if [5,6,7] in i:
... print i[-1]
...
8
[5, 6, 7] is not an item of the aList you show, so the if will fail, and your question as posed just doesn't pertain. More generally, the loop implied in such an if tosses away the index anyway. A way to make your code snippet work would be, instead of the if, to have something like (Python 2.6 or better -- honk if you need to work on different versions):
where = next((x for x in aList if x[0] == element), None)
if where:
print(x[1])
More generally, the expressions in the next and in the print must depend on the exact "fine grained" structure of aList -- in your example, x[0] and x[1] work just fine, but in a slightly different example you may need different expressions. There is no "generic" way that totally ignores how your data is actually structured and "magically works anyway"!-)
The code in your question is sort of weird. But, assuming you're learning the basics:
Getting the index of an element:
it's actually simple: list.index(element). Assuming of course, the element only appears once. If it appears more than once, you can use the extra parameters:
list.index(element, start_index): here it will start searching from start_index. There's also:
list.index(element, start_index, end_index): I think it's self explanitory.
Getting the index in a for loop
If you're looping on a list and you want to loop on both the index and the element, the pythonic way is to enumerate the list:
for index, element in enumerate(some_list):
# here, element is some_list[index]
Here, enumerate is a function that takes a list and returns a list of tuples. Say your list is ['a', 'b', 'c'], then enumerate would return: [ (1, 'a'), (2, 'b'), (3, 'c') ]
When you iterate over that, each item is a tuple, and you can unpack that tuple.
tuple unpacking is basically like this:
>>> t = (1, 'a')
>>> x, y = t
>>> t
(1, 'a')
>>> x
1
>>> y
'a'
>>>
One possible solution.
aList = [ ([1,2,3],4) , ([5,6,7],8) ]
element = [5,6,7]
>>> print(*[y for x,y in aList if element == x])
8