I have a dictionary like this
dic={10:(1,4),20:(2,4),30:(3,4)}
how to get 1,2,3 as output using dic.values() without using for loop.
This works:
>>> dic={10:(1,4),20:(2,4),30:(3,4)}
>>> [x[0] for x in dic.values()]
[1, 2, 3]
>>> # Or if you want that as a tuple
>>> tuple(x[0] for x in dic.values())
(1, 2, 3)
>>> # Or a string
>>> ",".join([str(x[0]) for x in dic.values()])
'1,2,3'
>>>
You should remember though that the order of dictionaries is not guaranteed. Meaning, the key/value pairs will not always be in the same order the you put them in.
To get disordered results in the order you want, you should look at sorted.
If you look at what dic.values() produces:
>>> dic={10:(1,4),20:(2,4),30:(3,4)}
>>> dic.values()
[(1, 4), (2, 4), (3, 4)]
Obviously you want the first element of each tuple.
You can use zip to get that without looping1.
>>> zip(*dic.values())[0]
(1, 2, 3)
As pointed out in comments, an even more efficient solution is:
>>> from itertools import izip
>>> next(izip(*dic.itervalues()))
(1, 2, 3)
Then you do not have to go all the way though creating several lists just to get the first element.
The order, of course, depends on the order of the keys in dic.
1 The 'without looping' is a silly distinction IMHO. Every solution either has an explicit or implicit loop in it...
Answer: You can't. You'll have to loop through the dictionary:
for v in d.values():
print v[0]
Or using a list comprehension:
[v[0] for v in d.values()]
This filtering methods are the best you can find :)
This solution is not any better than using iterators, but it has a different approach and maybe it is more suitable for complex tasks:
from operator import itemgetter
dic={10:(1,4),20:(2,4),30:(3,4)}
print map(itemgetter(0), dic.values())
gives:
[1, 2, 3]
How about using map here.
map(lambda x: x[0], dic.values())
Related
I have a list like [ ((xs,xe),idx),...]
I want to collect xs and xe into a set,like this way
s={ xs,xe for ((xs,xe),idx)
I know I can use it two times and add xs,xe respectively.
Is there a better way to do it?
You can use itertools.chain.from_iterable
>>> import itertools
>>> lst = [((1,2), 'a'), ((3,4), 'b')]
>>> s = set(itertools.chain.from_iterable(pair for pair, _ in lst))
>>> s
set([1, 2, 3, 4])
I have a python list:
[ (2,2),(2,3),(1,4),(2,2), etc...]
What I need is some kind of function that reduces it to its unique components... which would be, in the above list:
[ (2,2),(2,3),(1,4) ]
numpy unique does not quite do this. I can think of a way to do it--convert my tuples to numbers, [22,23,14,etc.], find the uniques, and work back from there...but I don't know if the complexity won't get out of hand. Is there a function that will do what I am trying to do with tuples?
Here is a sample of code that demonstrates the problem:
import numpy as np
x = [(2,2),(2,2),(2,3)]
y = np.unique(x)
returns: y: [2 3]
And here is the implementation of the solution that demonstrates the fix:
x = [(2,2),(2,2),(2,3)]
y = list(set(x))
returns y: [(2,2),(2,3)]
If order does not matter
If the order of the result is not critical, you can convert your list to a set (because tuples are hashable) and convert the set back to a list:
>>> l = [(2,2),(2,3),(1,4),(2,2)]
>>> list(set(l))
[(2, 3), (1, 4), (2, 2)]
If order matters
(UPDATE)
As of CPython 3.6 (or any Python 3.7 version) regular dictionaries remember their insertion order, so you can simply issue.
>>> l = [(2,2),(2,3),(1,4),(2,2)]
>>> list(dict.fromkeys(l))
[(2, 2), (2, 3), (1, 4)]
(OLD ANSWER)
If the order is important, the canonical way to filter the duplicates is this:
>>> seen = set()
>>> result = []
>>> for item in l:
... if item not in seen:
... seen.add(item)
... result.append(item)
...
>>> result
[(2, 2), (2, 3), (1, 4)]
Finally, a little slower and a bit more hackish, you can abuse an OrderedDict as an ordered set:
>>> from collections import OrderedDict
>>> OrderedDict.fromkeys(l).keys() # or list(OrderedDict.fromkeys(l)) if using a version where keys() does not return a list
[(2, 2), (2, 3), (1, 4)]
Using a set will remove duplicates, and you create a list from it afterwards:
>>> list(set([ (2,2),(2,3),(1,4),(2,2) ]))
[(2, 3), (1, 4), (2, 2)]
you could simply do
y = np.unique(x, axis=0)
z = []
for i in y:
z.append(tuple(i))
The reason is that a list of tuples is interpreted by numpy as a 2D array. By setting axis=0, you'd be asking numpy not to flatten the array and return unique rows.
set() will remove all duplicates, and you can then put it back to a list:
unique = list(set(mylist))
Using set(), however, will kill your ordering. If the order matters, you can use a list comprehension that checks if the value already exists earlier in the list:
unique = [v for i,v in enumerate(mylist) if v not in mylist[:i]]
That solution is a little slow, however, so you can do it like this:
unique = []
for tup in mylist:
if tup not in unique:
unique.append(tup)
Sorry if this has already been asked, I couldn't find it anywhere. Basically how do I get 2 separate ranges within a list in Python.
If I want the 1st, 2nd, 5th and 6th elements of a list I know I can do this,
l = range(0,15)
l[1:3]+l[5:7]
but this assumes that l is easy to write. However I am scrapping something from a webpage using BeautifulSoup4, so I'm using soup.find_all (which gives me a list), so I can't simply write out 2 lists, l and concatenate them.
I want an answer that is something like
l = range(0,15)
l[1:3,5:7]
(but of course without the error) :)
This might be what you want. itemgetter creates a function that retrieves the listed indices:
>>> import operator
>>> snip = operator.itemgetter(1,2,5,6)
>>> snip(range(15))
(1, 2, 5, 6)
>>> snip('abcdefg')
('b', 'c', 'f', 'g')
>>> snip([1,2,3,4,5,6,7,8])
(2, 3, 6, 7)
I would do this with a function:
def multi_range(l, *args):
output = []
for indices in args:
output += l[indices[0]:indices[1]]
return output
So the first argument would be the list, and the rest of the parameters are tuples with the indices you're looking to pull. It would work fine with a long list name:
long_list_name = range(0, 15)
print multi_range(long_list_name, (1, 3), (5, 7))
>>> [1, 2, 5, 6]
l = range(0, 15)
print([l[i] for i in [1,2, 5,6]])
Not sure why you think l[1:3]+l[5:7] is hard, find_all returns a normal python list like any other.
Or using map:
l = range(0, 15)
print(list(map(l.__getitem__,(1,2,5,6))))
Is this OK?
indices = [1, 2, 5, 6]
selected = [l[i] for i in indices]
I have two lists and dictionary as follows:
>>> var1=[1,2,3,4]
>>> var2=[5,6,7]
>>> dict={1:var1,2:var2}
I want to find the size of the mutable element from my dictionary i.e. the length of the value for a key.
After looking up the help('dict'), I could only find the function to return number of keys i.e. dict.__len__().
I tried the Java method(hoping that it could work) i.e. len(dict.items()[0]) but it evaluated to 2.
I intend to find this:
Length of value for first key: 4
Length of value for second key: 3
when the lists are a part of the dictionary and not as individual lists in case their length is len(list).
Any suggestions will be of great help.
dict.items() is a list containing all key/value-tuples of the dictionary, e.g.:
[(1, [1,2,3,4]), (2, [5,6,7])]
So if you write len(dict.items()[0]), then you ask for the length of the first tuple of that items-list. Since the tuples of dictionaries are always 2-tuples (pairs), you get the length 2. If you want the length of a value for a given key, then write:
len(dict[key])
Aso: Try not to use the names of standard types (like str, dict, set etc.) as variable names. Python does not complain, but it hides the type names and may result in unexpected behaviour.
You can do this using a dict comprehension, for example:
>>> var1 = [1,2,3,4]
>>> var2 = [5,6,7]
>>> d = {1:var1, 2:var2}
>>> lengths = {key:len(value) for key,value in d.iteritems()}
>>> lengths
{1: 4, 2: 3}
Your "Java" method would also nearly have worked, by the way (but is rather unpythonic). You just used the wrong index:
>>> d.items()
[(1, [1, 2, 3, 4]), (2, [5, 6, 7])]
>>> d.items()[0]
(1, [1, 2, 3, 4])
>>> len(d.items()[0][1])
4
>>>for k,v in dict.iteritems():
k,len(v)
ans:-
(1, 4)
(2, 3)
or
>>>var1=[1,2,3,4]
>>>var2=[5,6,7]
>>>dict={1:var1,2:var2}
ans:-
>>>[len(v) for k,v in dict.iteritems()]
[4, 3]
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.