Using enumerate() to enumerate items with letters rather than numbers - python

I'm trying to use the built-in function enumerate() to label some points or vertices where each point is represented by its coordinates in a list(or set) of tuples which essentially looks like {(4,5), (6,8), (1,2)}
I want to assign a letter starting from "a" in ascending order to each tuple in this set, using enumerate() does exactly the same but It's written in a way that it returns the value of the index of each item so that it's a number starting from 0.
is there any way to do it other than writing my own enumerate()?

Check this out:
import string
tup = {(4,5), (6,8), (1,2)}
dic = {i: j for i, j in zip(string.ascii_lowercase, tup)}
This returns:
{'a': (4, 5), 'b': (6, 8), 'c': (1, 2)}

This is enumerate's signature.
enumerate(iterable, start=0)
Use start as 65 for 'A' and 97 for 'a'.
lst=[(1,2),(2,3),(3,4),...]
for idx,val in enumerate(lst,65):
print(chr(idx),val)
A (1, 2)
B (2, 3)
C (3, 4)

Maybe this is a way to get what you want, using chr():
L = [(4,5), (6,8), (1,2)]
for k, v in enumerate(L):
print(chr(65 + k), v)
Output :
A (4, 5)
B (6, 8)
C (1, 2)

The enumerate function is defined as follow :
enumerate(iterable, start=0)
I think just have to write your own enumerate or an wrapper around enumerate.

Related

How can I save the original index after sorting a list?

Let's say I have the following array:
a = [4,2,3,1,4]
Then I sort it:
b = sorted(A) = [1,2,3,4,4]
How could I have a list that map where each number was, ex:
position(b,a) = [3,1,2,0,4]
to clarify this list contains the positions not values)
(ps' also taking in account that first 4 was in position 0)
b = sorted(enumerate(a), key=lambda i: i[1])
This results is a list of tuples, the first item of which is the original index and second of which is the value:
[(3, 1), (1, 2), (2, 3), (0, 4), (4, 4)]
def position(a):
return sorted(range(len(a)), key=lambda k: a[k])

Sorting in a dictionary [duplicate]

This question already has answers here:
How do I sort a dictionary by value?
(34 answers)
Closed 2 years ago.
Im trying to get the output from my dictionary to be ordered from their values in stead of keys
Question:
ValueCount that accepts a list as a parameter. Your function will return a list of tuples. Each tuple will contain a value and the number of times that value appears in the list
Desired outcome
>>> data = [1,2,3,1,2,3,5,5,4]
>>> ValueCount(data)
[(1, 2), (2, 2), (5, 1), (4, 1)]
My code and outcome
def CountValues(data):
dict1 = {}
for number in data:
if number not in dict1:
dict1[number] = 1
else:
dict1[number] += 1
tuple_data = dict1.items()
lst = sorted(tuple_data)
return(lst)
>>>[(1, 2), (2, 2), (3, 2), (4, 1), (5, 2)]
How would I sort it ascendingly by using the values instead of keys.
If you want to sort by the values(second item in each tuple), specify key:
sorted(tuple_data, key=lambda x: x[1])
Or with operator.itemgetter:
sorted(tuple_data, key=operator.itemgetter(1))
Also as a side note, your counting code:
dict1 = {}
for number in data:
if number not in dict1:
dict1[number] = 1
else:
dict1[number] += 1
Can be simplified with collections.Counter:
dict1 = collections.Counter(data)
With all the above in mind, your code could look like this:
from operator import itemgetter
from collections import Counter
def CountValues(data):
counts = Counter(data)
return sorted(counts.items(), key=itemgetter(1))
print(CountValues([1,2,3,1,2,3,5,5,4]))
# [(4, 1), (1, 2), (2, 2), (3, 2), (5, 2)]
You can use the sorted with the help of key parameter. it is not a in-place sorting . Thus it never modifies the original array.
for more
In [18]: data = [1,2,3,1,2,3,5,5,4]
In [19]: from collections import Counter
In [20]: x=Counter(data).items()
#Sorted OUTPUT
In [21]: sorted(list(x), key= lambda i:i[1] )
Out[21]: [(4, 1), (1, 2), (2, 2), (3, 2), (5, 2)]
In [22]: x
Out[22]: dict_items([(1, 2), (2, 2), (3, 2), (5, 2), (4, 1)])
"Sort" function uses first element of data.
To sort dictionary by its values you can use for-loop for values:
d={1:1,2:2,5:2,4:3,3:2}
x=[]
for i in set(sorted(d.values())):
for j in sorted(d.items()):
if j[1]==i:
x.append(j)
print(x)
if you don't convert sorted(d.values()) to set{} , it will check every value, even there are same numbers. For example if your values list is [1,2,2,3] , it will check items for value "2" two times and as a result your sorted list will contain repeated data which both have value "2" . But set{} keeps only one of each element and in this case, for-loop will check every different value of d.values() . And if there are items with a same value, code will sort them by keys because of sorted(d.items()) .
(to understand better you can use this code without that set{} and use d.items() instead of sorted(d.items()))

I get the empty set when using the for loop

I know this must be something very basic, but I dont know why I keep getting an empty set. What should I do in order to not get an empty set?
s=set()
for a in [(1,2),(1,3),(1,2)]:
b=[]
for j in range(len(a)-1):
b.append(a)
s.union(b)
print(s)
I get:
s=([])
but the result I want is
{(1,2),(1,3)}
I know there is another way to take the union, but I wish to do so with this for loop.
Try this:
s = set()
s = s.union([(1,2),(1,3),(1,2)])
set.union doesn't modify the set, so you need to save the result
if you want to use a for-loop, as you did in your post, then make sure to save the result of the union: s = s.union(b)
The function union returns a set that is the union of s with b, you should change your code to:
s = set()
for a in [(1, 2), (1, 3), (1, 2)]:
b = []
for j in range(len(a) - 1):
b.append(a)
s = s.union(b)
print(s)
Output
{(1, 2), (1, 3)}
As an alternative you can use the update function:
s.update(b)
Output
{(1, 2), (1, 3)}
You only need the union method if you want to union two non-empty sets. Since you start with an empty set, you can simply use the set constructor:
s = set([(1,2),(1,3),(1,2)])
and s would become:
{(1, 2), (1, 3)}

How to sort dictionary on first element of the key (tuple)

I have a dictionary where each key is a tuple of values, I want to use the sorted() method to sort the dictionary on the very first element of my tuple. My code looks like this:
def mapData(header_list, dict_obj):
master_dict = {}
client_section_list = []
for element in header_list:
for row in dict_obj:
if (row['PEOPLE_ID'], row['DON_DATE']) == element:
client_section_list.append(row)
element = list(element)
element_list = [client_section_list[0]['DEDUCT_AMT'],
client_section_list[0]['ND_AMT'],
client_section_list[0]['DEDUCT_YTD'],
client_section_list[0]['NONDEDUCT_YTD']
]
try:
element_list.append((float(client_section_list[0]['DEDUCT_YTD']) +
float(client_section_list[0]['NONDEDUCT_YTD'])
))
except ValueError:
pass
element.extend(element_list)
element = tuple(element)
master_dict[element] = client_section_list
client_section_list = []
return sorted(master_dict, key=lambda key: key[master_dict[(1)]]
The last line is where I'm trying to find a way to sort it. My tuple looks like this:
(312178078,6/22/15,25,0,25,0,25.0)
Not entirely sure what you are trying to do, particularly what that function is supposed to return. I assume that you want to return the dictionary sorted by the first element in the key-tuples.
For this, there are two things to note:
Tuples are by default sorted by their first element (and if those are the same, then by the second, and so on), so no special key function is required
Regular dictionaries are unordered, i.e. they can not be permanently sorted in any order; you can only sort their items as a list, or use that list to create an OrderedDict instead
Some minimal example:
>>> d = {(2,4): 1, (1,3): 2, (1,2): 3, (3,1): 4}
>>> sorted(d)
[(1, 2), (1, 3), (2, 4), (3, 1)]
>>> sorted(d.items())
[((1, 2), 3), ((1, 3), 2), ((2, 4), 1), ((3, 1), 4)]
>>> collections.OrderedDict(sorted(d.items()))
OrderedDict([((1, 2), 3), ((1, 3), 2), ((2, 4), 1), ((3, 1), 4)])
In your case, you probably want this:
return collections.OrderedDict(sorted(master_dict.items()))
As #tobias_k has mentioned, sorted sorts tuples by its elements with decreasing priority, e.g. if you take a tuple (a, b, c) the highest sorting priority goes to a, then goes b etc (by default sorted uses object's comparison methods and this is how tuple comparison works). So sorted(master_dict) is all you need if you want a list of sorted keys, yet I believe you really want to leave the values
sorted(master_dict.items(), key=lambda key: key[0])
dict.items returns tuples of form (key, value) so here you need to specify the sorting key.

Union with tuples Python

import itertools
list_with_tuples=[(1,), (2,), (3,)]
pairs = itertools.combinations(list_with_tuples, 2)
for pair in pairs:
print(pair)
so the result of pairs is :
((1,),(2,)) ,
((1,),(3)) ,
((2,),(3,))
How I can union them?
After union I want to do a dictionary like:
di={ (1,2): value1, (1,3): value2, (2,3): value3 }
How can I do this?
One way to "union" tuples in python is to simply add them:
>>> (1,) + (2,)
(1, 2)
So you can modify your example to add:
import itertools
list_with_tuples=[(1,), (2,), (3,)]
pairs = itertools.combinations(list_with_tuples, 2)
for left, right in pairs:
print(left + right)
Outputs:
(1, 2)
(1, 3)
(2, 3)
If you need to add n tuples, rather than just 2 of them, you can use sum and specify an initial value of the empty tuple () as the second argument.
Alternatively, as Kevin mentioned in the comments, you can build a new tuple by consuming the output of an itertools.chain, which will likely be more efficient if n is large.
You can use a dict comprehension to do this for you. Iterate over the itertools.combinations, index out the values from the tuple, then create your new tuple as the key and add them for the value.
>>> {(i[0],j[0]) : i[0] + j[0] for i,j in itertools.combinations(list_with_tuples, 2)}
{(1, 2): 3, (1, 3): 4, (2, 3): 5}
You can chain the elements into a single tuple:
from itertools import chain,combinations
list_with_tuples=[(1,), (2,), (3,)]
di = {tuple(chain.from_iterable(comb)):"value" for comb in combinations(list_with_tuples, 2)}
print(di)
{(1, 2): 'value', (1, 3): 'value', (2, 3): 'value'}
It will work for any length combinations.
If you have a another container that has the values you can zip:
from itertools import chain,combinations
list_with_tuples=[(1,), (2,), (3,)]
values = [1,2,3]
di = {tuple(chain.from_iterable(comb)): val for comb,val in zip(combinations(list_with_tuples, 2),values)}
print(di)
{(1, 2): 1, (1, 3): 2, (2, 3): 3}
You can join iterable objects such as tuples and lists together using itertools.chain():
list_with_tuples=[(1,), (2,), (3,)]
pairs = itertools.combinations(list_with_tuples, 2)
for pair in pairs:
print(tuple(itertools.chain(*pair)))
This also has the advantage of being lazy, so you can iterate over the chain one element at a time instead of making a full tuple out of it, if that's what you need. If pair is also a lazy iterator, you probably want to use itertools.chain.from_iterable() instead of the star operator.

Categories