Add a list of multisets in python - python

What is the pythonic way to merge a list of multisets into a single multiset?
For example,
from multiset import Multiset
set1 = Multiset('aab')
set2 = Multiset('abc')
ls = [set1, set2]
Based on using sets my guess was:
Multiset.add(*ls)
This gives an error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.7/site-packages/multiset.py", line 931, in add
self._elements[element] += multiplicity
TypeError: unhashable type: 'Multiset'
Is there a better way than a for loop, as below?
def add_multisets(ls):
result = Multiset()
for i in ls:
result += i
return result
>>> add_multisets(ls)
Multiset({'a': 3, 'b': 2, 'c': 1})

You can use Multiset.combine(*ls)
i.e
from multiset import Multiset
set1 = Multiset('aab')
set2 = Multiset('abc')
ls = [set1, set2]
x = Multiset.combine(*ls)
print(x) # Multiset({'a': 3, 'b': 2, 'c': 2})

Related

Convert python list of lists into R list of vectors in rpy2

I have a list of lists in python like the following like the following:
test = [[4, 2, 5, 3], [5, 2], [6, 3, 2, 5, 5]]
I want to input this into dunn.test in R using rpy2.
However, I am not sure how to convert this into a list of numeric vectors (R).
I am trying:
py2.robjects.ListVector(test)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3/dist-packages/rpy2/robjects/vectors.py", line 635, in __init__
kv = [(str(k), conversion.py2ri(v)) for k,v in tlist]
File "/usr/lib/python3/dist-packages/rpy2/robjects/vectors.py", line 635, in <listcomp>
kv = [(str(k), conversion.py2ri(v)) for k,v in tlist]
ValueError: too many values to unpack (expected 2)
What is the correct way of doing this?
See https://rpy2.github.io/doc/v2.9.x/html/vector.html#rpy2.robjects.vectors.ListVector
The constructor for ListVector can take a sequence of (name, value) pairs.
Try:
rpy2.robjects.ListVector([(str(i), x) for i, x in enumerate(test)])
If no name, the way to do it at the robjects level is currently to first create an R list of defined length and then populate it:
res = rpy2.robjects.ListVector.from_length(3)
for i, x in enumerate(test):
res[i] = rpy2.robjects.IntVector(x)

Performing calculations on some values in a dictionary based on their keys (Python)

Looking to gain some understanding on handling dictionaries efficiently in Python.
I have a dictionary
dict = {'a': 11, 'b': 4, 'c': 7, 'd': 12, 'e': 5}
and I would like to perform calculations only on a subset of its values. Which values to be considered in the calculations is based on their keys. Say, that these keys will be in a list of keys.
For example, if I would like to add the values of the keys a, b and e (i.e. keys_list_to_add=['a', 'b', 'e']) I would expect the result to be 20. Note, that several such subsets calculations may exist and a key may be missing (so, perhaps an exception should be raised in that case).
After seeing this answer, I tried to implement it with no success cause I am still learning Python. Could you please provide with code suggestions for my problem?
You can implement the given example with sum and generator expression that returns dict values based on keys:
>>> d = {'a': 11, 'b': 4, 'c': 7, 'd': 12, 'e': 5}
>>> keys_list_to_add = ['a', 'b', 'e']
>>> sum(d[k] for k in keys_list_to_add)
20
It raises KeyError in case that given key doesn't exists in the dict:
>>> keys_list_to_add = ['a', 'b', 'f']
>>> sum(d[k] for k in keys_list_to_add)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <genexpr>
KeyError: 'f'
If you want to handle the error in one way or another you could use try/except:
>>> try:
... sum(d[k] for k in keys_list_to_add)
... except KeyError:
... print 'Missing key'
...
Missing key
Or you could interpret missing key as 0:
>>> sum(d.get(k, 0) for k in keys_list_to_add)
15
Note that you shouldn't use build-in method names like dict for variables since that hides the method:
>>> dict(a=1)
{'a': 1}
>>> dict = {1:2}
>>> dict(a=1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'dict' object is not callable

TypeError: 'itertools.combinations' object is not subscriptable

When I try to run:
temp = (twoset2[x][i][0]-twoset[x][i][1])
I get:
TypeError: 'itertools.combinations' object is not subscriptable
My code:
for x in range(0,64):
for i in range(0,1):
temp = (twoset2[x][i][0]-twoset[x][i][1])
DSET[counter2]= temp
temp = 0
counter2 += 1
Basically what I am trying to do is: I have a list (twoset2) of 2 element subsets of coordinates (so an example: ((2,0) (3,3)). I want to access each individual coordinate, and then take the difference between x and y and place it into DSET, but I get the above error when trying to run.
Please help!
itertools.combinations returns a generator and not a list. What this means is that you can iterate over it but not access it element by element with an index as you are attempting to.
Instead you can get each combination like so:
import itertools
for combination in itertools.combinations([1,2,3], 2):
print combination
This gives:
(1, 2)
(1, 3)
(2, 3)
twoset2 is not a list; it is an itertools.combinations object (which does not support indexing):
>>> import itertools
>>> itertools.combinations([1, 2, 3], 2)
<itertools.combinations object at 0x01ACDC30>
>>>
>>> twoset2 = itertools.combinations([1, 2, 3], 2)
>>> twoset2[0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'itertools.combinations' object is not subscriptable
>>>
You will need to explicitly convert this into a list if you want a list:
twoset2 = list(itertools.combinations(...))

How can you join int and list together?

But I still can't find the join function anywhere else on the internet. The main problem is that the head(items) is int and tail(items) is list, and I can't combine head and tail together. Here is the code I tried:
def head(items):
return items[0]
def tail(items):
return items[1:]
def isEven(x):
return x % 2 == 0
def extractEvens(items):
if (items == None):
return None
elif (isEven(head(items))):
return join(head(items),extractEvens(tail(items)))
else:
return extractEvens(tail(items))
a = [4,2,5,2,7,0,8,3,7]
print(extractEvens(a))
Here is the link for the page I tried to study: The is the code for filter pattern:
link_of_code
You can also try insert which is even more useful as the head must be in the starting.
l = extractEvens(tail(items))
l.insert(0,head(items))
return l
Please, provide an example of the desired output.
If you want to create a new list, merging a list with an int, it should be:
return [head(items)] + tail(items)
what you need is append
>>> a=6
>>> b=[1,2,3,4]
>>> b.append(a)
>>> b
[1, 2, 3, 4, 6]
here you just cant concanate list and int:
>>> a=6
>>> b=[1,2,3,4]
>>> a+b
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'list'
>>> list(a)+b
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable
but if you do str, it will concanated as str not int:
>>> list(str(a))+b
['6', 1, 2, 3, 4]
There are multiple errors in your code:
def isEven(x):
return x % 2 == 0 # x % 2 not x % ==
def extractEvens(items):
if not items:
return [] # return empty list not None
elif isEven(head(items)):
# convert ints to strings and put head(items) in a list
return "".join(map(str,[head(items)]) + map(str,extractEvens(tail(items))))
else:
return extractEvens(tail(items))
You can also do this in a single list comprehension:
a = [4, 2, 5, 2, 7, 0, 8, 3, 7]
print("".join([str(x) for x in a if not x % 2]))

Strange error with range type in list assignment

r = range(10)
for j in range(maxj):
# get ith number from r...
i = randint(1,m)
n = r[i]
# remove it from r...
r[i:i+1] = []
The traceback I am getting a strange error:
r[i:i+1] = []
TypeError: 'range' object does not support item assignment
Not sure why it is throwing this exception, did they change something in Python 3.2?
Good guess: they did change something. Range used to return a list, and now it returns an iterable range object, very much like the old xrange.
>>> range(10)
range(0, 10)
You can get an individual element but not assign to it, because it's not a list:
>>> range(10)[5]
5
>>> r = range(10)
>>> r[:3] = []
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
r[:3] = []
TypeError: 'range' object does not support item assignment
You can simply call list on the range object to get what you're used to:
>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> r = list(range(10))
>>> r[:3] = [2,3,4]
>>> r
[2, 3, 4, 3, 4, 5, 6, 7, 8, 9]
Try this for a fix (I'm not an expert on python 3.0 - just speculating at this point)
r = [i for i in range(maxj)]

Categories