how to convert a set in python into a dictionary - python

I am new to python and trying to convert a Set into a Dictionary. I am struggling to find a way to make this possible. Any inputs are highly appreciated. Thanks.
Input : {'1438789225', '1438789230'}
Output : {'1438789225':1, '1438789230':2}

Use enumerate() to generate a value starting from 0 and counting upward for each item in the dictionary, and then assign it in a comprehension:
input_set = {'1438789225', '1438789230'}
output_dict = {item:val for val,item in enumerate(input_set)}
Or a traditional loop:
output_dict = {}
for val,item in enumerate(input_set):
output_dict[item] = val
If you want it to start from 1 instead of 0, use item:val+1 for the first snippet and output_dict[item] = val+1 for the second snippet.
That said, this dictionary would be pretty much the same as a list:
output = list(input_set)

My one-liner:
output = dict(zip(input_set, range(1, len(s) + 1)))
zip mixes two lists (or sets) element by element (l1[0] + l2[0] + l1[1] + l2[1] + ...).
We're feeding it two things:
the input_set
a list from 1 to the length of the set + 1 (since you specified you wanted to count from 1 onwards, not from 0)
The output is a list of tuples like [('1438789225', 1), ('1438789230', 2)] which can be turned into a dict simply by feeding it to the dict constructor... dict.
But like TigerhawkT3 said, I can hardly find a use for such a dictionary. But if you have your motives there you have another way of doing it. If you take away anything from this post let it be the existence of zip.

an easy way of doing this is by iterating on the set, and populating the result dictionary element by element, using a counter as dictionary key:
def setToIndexedDict(s):
counter = 1
result = dict()
for element in s:
result[element] = counter #adding new element to dictionary
counter += 1 #incrementing dictionary key
return result

My Python is pretty rusty, but this should do it:
def indexedDict(oldSet):
dic = {}
for elem,n in zip(oldSet, range(len(oldSet)):
dic[elem] = n
return dic
If I wrote anything illegal, tell me and I'll fix it. I don't have an interpreter handy.
Basically, I'm just zipping the list with a range object (basically a continuous list of numbers, but more efficient), then using the resulting tuples.
Id got with Tiger's answer, this is basically a more naive version of his.

Related

Remove subset of an element from a list if there are more than one

If I have a list like:
[u'test_1', u'test_2', u'test_3', u'bananas_4', u'cake_5', u'bananas_6']
What would be the best way to just get the following without knowing anything else in advance?
[u'test_1', u'bananas_4', u'cake_5']
So how I see it, would be something like loop over the list, store the test and bananas somehow, and if on another iteration, see another of the same start of the string, remove that from the list.
Does anyone know the best way of achieving this?
My main idea uses the dictionary functionality that items are not overridden by default.
I used OrderedDict to keep the order of insertion of items.
lst = [u'test_1', u'test_2', u'test_3', u'bananas_4', u'cake_5', u'bananas_6']
d = OrderedDict()
for item in lst:
key, val = item.split('_')
d.setdefault(key, val) # will not override if item was there before
new_list = [key + '_' + val for key,val in d.items()]
print new_list
Output is
[u'test_1', u'bananas_4', u'cake_5']
Simply keep a set of your prefixes and only add items to your filtered list if they're not in the prefix list:
start = [u'test_1', u'test_2', u'test_3', u'bananas_4', u'cake_5', u'bananas_6']
seen = set()
end = []
for item in start:
prefix = item.partition('_')[0]
if prefix not in seen:
end.append(item)
seen.add(prefix)
print(end) # ['test_1', 'bananas_4', 'cake_5']
I would split it into two sections. The first is to split the string in the list by "_" then you would have the raw information [test,test,test,banana,cake,banana] and another with the numbers [1,2,3,4,5,6]
You could then find the uniques of the string list with the following solution:
Get unique values from a list in python. Finally append the numbers back on.

adding to a variable in a nested list comprehension

I'm attempting to make a nested list comprehension, but I can't figure out how I should do it. currently, I have a loop like this:
filtered = []
p = -1
for i in list:
p += 1
for k in list_of_lists[p]:
if not k in filter:
filtered.append(k)
While this works, it takes about 5-8 seconds for it to complete, and this amount of time is nearly unacceptable for the circumstance that it is being used. I'm trying to make it in to a list comprehension, but I can't seem to figure out a way to make the p += 1 in the list comprehension. I attempted this:
filtered = [i for i in list for k ind list_of_list[p], p+=1]
but it clearly doesn't work. I was wondering if there was anyway to get around this.
I would flatten it and then convert it to a set because you can't self reference inside a list comprehension. The difference is a set can only have one of each item and order is not enforced.
list_of_lists = [["blue","green","red"],["red","yellow","white"],["orange","yellow","green"]]
filtered = set(y for x in list_of_lists for y in x)
print(filtered)

Find how many lists in list have the same element

I am new at Python, so I'm having trouble with something. I have a few string lists in one list.
list=[ [['AA','A0'],['AB','A0']],
[['AA','B0'],['AB','A0']],
[['A0','00'],['00','A0'], [['00','BB'],['AB','A0'],['AA','A0']] ]
]
And I have to find how many lists have the same element. For example, the correct result for the above list is 3 for the element ['AB','A0'] because it is the element that connects the most of them.
I wrote some code...but it's not good...it works for 2 lists in list,but not for more....
Please,help!
This is my code...for the above list...
for t in range(0,len(list)-1):
pattern=[]
flag=True
pattern.append(list[t])
count=1
rest=list[t+1:]
for p in pattern:
for j in p:
if flag==False:
break
pair= j
for i in rest:
for y in i:
if pair==y:
count=count+1
break
if brojac==len(list):
flag=False
break
Since your data structure is rather complex, you might want to build a recursive function, that is a function that calls itself (http://en.wikipedia.org/wiki/Recursion_(computer_science)).
This function is rather simple. You iterate through all items of the original list. If the current item is equal to the value you are searching for, you increment the number of found objects by 1. If the item is itself a list, you will go through that sub-list and find all matches in that sub-list (by calling the same function on the sub-list, instead of the original list). You then increment the total number of found objects by the count in your sub-list. I hope my explanation is somewhat clear.
alist=[[['AA','A0'],['AB','A0']],[['AA','B0'],['AB','A0']],[['A0','00'],['00','A0'],[['00','BB'],['AB','A0'],['AA','A0']]]]
def count_in_list(val, arr):
val_is_list = isinstance(val, list)
ct = 0
for item in arr:
item_is_list = isinstance(item, list)
if item == val or (val_is_list and item_is_list and sorted(item) == sorted(val)):
ct += 1
if item_is_list :
ct += count_in_list(val, item)
return ct
print count_in_list(['AB', 'A0'], alist)
This is an iterative approach that will also work using python3 that will get the count of all sublists:
from collections import defaultdict
d = defaultdict(int)
def counter(lst, d):
it = iter(lst)
nxt = next(it)
while nxt:
if isinstance(nxt, list):
if nxt and isinstance(nxt[0], str):
d[tuple(nxt)] += 1
rev = tuple(reversed(nxt))
if rev in d:
d[rev] += 1
else:
lst += nxt
nxt = next(it,"")
return d
print((counter(lst, d)['AB', 'A0'])
3
It will only work on data like your input, nesting of strings beside lists will break the code.
To get a single sublist count is easier:
def counter(lst, ele):
it = iter(lst)
nxt = next(it)
count = 0
while nxt:
if isinstance(nxt, list):
if ele in (nxt, nxt[::-1]):
count += 1
else:
lst += nxt
nxt = next(it, "")
return count
print(counter(lst, ['AB', 'A0']))
3
Ooookay - this maybe isn't very nice and straightforward code, but that's how i'd try to solve this. Please don't hurt me ;-)
First,
i'd fragment the problem in three smaller ones:
Get rid of your multiple nested lists,
Count the occurence of all value-pairs in the inner lists and
Extract the most occurring value-pair from the counting results.
1.
I'd still use nested lists, but only of two-levels depth. An outer list, to iterate through, and all the two-value-lists inside of it. You can finde an awful lot of information about how to get rid of nested lists right here. As i'm just a beginner, i couldn't make much out of all that very detailed information - but if you scroll down, you'll find an example similar to mine. This is what i understand, this is how i can do.
Note that it's a recursive function. As you mentioned in comments that you think this isn't easy to understand: I think you're right. I'll try to explain it somehow:
I don't know if the nesting depth is consistent in your list. and i don't want to exctract the values themselves, as you want to work with lists. So this function loops through the outer list. For each element, it checks if it's a list. If not, nothing happens. If it is a list, it'll have a look at the first element inside of that list. It'll check again if it's a list or not.
If the first element inside the current list is another list, the function will be called again - recursive - but this time starting with the current inner list. This is repeated until the function finds a list, containing an element on the first position that is NOT a list.
In your example, it'll dig through the complete list-of-lists, until it finds your first string values. Then it gets the list containing this value - and put that in another list, the one that is returned.
Oh boy, that sounds really crazy - tell me if that clarified anything... :-D
"Yo dawg, i herd you like lists, so i put a list in a list..."
def get_inner_lists(some_list):
inner_lists = []
for item in some_list:
if hasattr(item, '__iter__') and not isinstance(item, basestring):
if hasattr(item[0], '__iter__') and not isinstance(item[0], basestring):
inner_lists.extend(get_inner_lists(item))
else:
inner_lists.append(item)
return inner_lists
Whatever - call that function and you'll find your list re-arranged a little bit:
>>> foo = [[['AA','A0'],['AB','A0']],[['AA','B0'],['AB','A0']],[['A0','00'],['00','A0'],[['00','BB'],['AB','A0'],['AA','A0']]]]
>>> print get_inner_lists(foo)
[['AA', 'A0'], ['AB', 'A0'], ['AA', 'B0'], ['AB', 'A0'], ['A0', '00'], ['00', 'A0'], ['00', 'BB'], ['AB', 'A0'], ['AA', 'A0']]
2.
Now i'd iterate through that lists and build a string with their values. This will only work with lists of two values, but as this is what you showed in your example it'll do. While iterating, i'd build up a dictionary with the strings as keys and the occurrence as values. That makes it really easy to add new values and raise the counter of existing ones:
def count_list_values(some_list):
result = {}
for item in some_list:
str = item[0]+'-'+item[1]
if not str in result.keys():
result[str] = 1
else:
result[str] += 1
return result
There you have it, all the counting is done. I don't know if it's needed, but as a side effect there are all values and all occurrences:
>>> print count_list_values(get_inner_lists(foo))
{'00-A0': 1, '00-BB': 1, 'A0-00': 1, 'AB-A0': 3, 'AA-A0': 2, 'AA-B0': 1}
3.
But you want clear results, so let's loop through that dictionary, list all keys and all values, find the maximum value - and return the corresponding key. Having built the string-of-two-values with a seperator (-), it's easy to split it and make a list out of it, again:
def get_max_dict_value(some_dict):
all_keys = []
all_values = []
for key, val in some_dict.items():
all_keys.append(key)
all_values.append(val)
return all_keys[all_values.index(max(all_values))].split('-')
If you define this three little functions and call them combined, this is what you'll get:
>>> print get_max_dict_value(count_list_values(get_inner_lists(foo)))
['AB', 'A0']
Ta-Daa! :-)
If you really have such lists with only nine elements, and you don't need to count values that often - do it manually. By reading values and counting with fingers. It'll be so much easier ;-)
Otherwise, here you go!
Or...
...you wait until some Guru shows up and gives you a super fast, elegant one-line python command that i've never seen before, which will do the same ;-)
This is as simple as I can reasonably make it:
from collections import Counter
lst = [ [['AA','A0'],['AB','A0']],
[['AA','B0'],['AB','A0']],
[['A0','00'],['00','A0'], [['00','BB'],['AB','A0'],['AA','A0']] ]
]
def is_leaf(element):
return (isinstance(element, list) and
len(element) == 2 and
isinstance(element[0], basestring)
and isinstance(element[1], basestring))
def traverse(iterable):
for element in iterable:
if is_leaf(element):
yield tuple(sorted(element))
else:
for value in traverse(element):
yield value
value, count = Counter(traverse(lst)).most_common(1)[0]
print 'Value {!r} is present {} times'.format(value, count)
The traverse() generate yields a series of sorted tuples representing each item in your list. The Counter object counts the number of occurrences of each, and its .most_common(1) method returns the value and count of the most common item.
You've said recursion is too difficult, but I beg to differ: it's the simplest way possible to attack this problem. The sooner you come to love recursion, the happier you'll be. :-)
Hopefully soemthing like this is what you were looking for. It is a bit tenuous and would suggest that recursion is better. But Since you didn't want it that way here is some code that might work. I am not super good at python but hope it will do the job:
def Compare(List):
#Assuming that the list input is a simple list like ["A1","B0"]
myList =[[['AA','A0'],['AB','A0']],[['AA','B0'],['AB','A0']],[['A0','00'],['00','A0'],[['00','BB'],['AB','A0'],['AA','A0']]]]
#Create a counter that will count if the elements are the same
myCounter = 0;
for innerList1 in myList:
for innerList2 in innerList1
for innerList3 in innerList2
for element in innerList3
for myListElements in myList
if (myListElements == element)
myCounter = myCounter + 1;
#I am putting the break here so that it counts how many lists have the
#same elements, not how many elements are the same in the lists
break;
return myCounter;

How does the enumerate function work?

I am supposed to do the following:
Define a function my_enumerate(items) that behaves in a similar way to the built-in enumerate function. It should return a list of pairs (i, item) where item is the ith item, with 0 origin, of the list items (see the examples below). Check the test cases for how the function should work. Your function must not call Python's in-built enumerate function.
Examples:
Input:
ans = my_enumerate([10, 20, 30])
print(ans)
Output:
[(0, 10), (1, 20), (2, 30)]
What does enumerate do? Try expressing it in English, and it may help you understand how to write the necessary code. If it doesn't then the practice of learning English language descriptions into code will be useful.
One way of describing enumerate is to say it iterates over each item in the list, and for each item in the input list it produces a pair of the item's index in the input list and the item.
So we know we need to iterate over the list:
for item in input_list:
pass
And we need to keep track of the index of the current item.:
index = 0
for item in input_list:
index += 1
Hmm, there's a better way of doing that:
for index in range(len(input_list)):
pass
Now to produce the pairs:
for index in range(len(input_list)):
pair = index, input_list[index]
You also need somewhere to store these pairs:
def my_enumerate(input_list):
output_list = []
for index in range(len(input_list)):
pair = index, input_list[index]
output_list.append(pair)
return output_list
Are there other ways to write code that produces the same output? Yes. Is this the best way to write this function? Not by a long shot. What this exercise should help you with is turning your thoughts into code, as you gain more experience doing that then you can combine multiple steps at a time, and start using more complicated programming concepts.
Use itertools.count and zip:
from itertools import count
def my_enumerate(values):
return list(zip(count(), values))

Max Value within a List of Lists of Tuple

I have a problem to get the highest Value in a dynamic List of Lists of Tuples.
The List can looks like this:
adymlist = [[('name1',1)],[('name2',2),('name3',1), ...('name10', 20)], ...,[('name m',int),..]]
Now I loop through the List to get the highest Value (integer):
total = {}
y=0
while y < len(adymlist):
if len(adymlist) == 1:
#has the List only 1 Element -> save it in total
total[adymlist[y][0][0]] = adymlist[y][0][1]
y += 1
else:
# here is the problem
# iterate through each lists to get the highest Value
# and you dont know how long this list can be
# safe the highest Value in total f.e. total = {'name1':1,'name10':20, ..}
I tried a lot to get the maximum Value but I found no conclusion to my problem. I know i must loop through each Tuple in the List and compare it with the next one but it dont know how to code it correct.
Also I can use the function max() but it doesnt work with strings and integers. f.e.
a = [ ('a',5),('z',1)] -> result is max(a) ---> ('z',1) obv 5 > 1 but z > a so I tried to expand the max function with max(a, key=int) but I get an Type Error.
Hope you can understand what I want ;-)
UPDATE
Thanks so far.
If I use itertools.chain(*adymlist) and max(flatlist, key=lambda x: x[1])
I will get an exception like : max_word = max(flatlist, key=lambda x: x[1])
TypeError: 'int' object is unsubscriptable
BUT If I use itertools.chain(adymlist) it works fine. But I dont know how to summate all integers from each Tuple of the List. I need your help to figure it out.
Otherwise I wrote a workaround for itertools.chain(*adymlist) to get the sum of all integers and the highest integer in that list.
chain = itertools.chain(*adymlist)
flatlist = list(chain)
# flatlist = string, integer, string, integer, ...
max_count = max(flatlist[1:len(flatlist):2])
total_count = sum(flatlist[1:len(flatlist):2])
# index of highest integer
idx = flatlist.index(next((n for n in flatlist if n == max_count)))
max_keyword = flatlist[idx-1]
It still does what I want, but isn't it to dirty?
To clarify, looks like you've got a list of lists of tuples. It doesn't look like we care about what list they are in, so we can simplify this to two steps
Flatten the list of lists to a list of tuples
Find the max value
The first part can be accomplished via itertools.chain (see e.g., Flattening a shallow list in Python)
The second can be solved through max, you have the right idea, but you should be passing in a function rather than the type you want. This function needs to return the value you've keyed on, in this case ,the second part of the tuple
max(flatlist, key=lambda x: x[1])
Correction
I re-read your question - are you looking for the max value in each sub-list? If this is the case, then only the second part is applicable. Simply iterate over your list for each list
A bit more pythonic than what you currently have would like
output = []
for lst in lists:
output.append( max(flatlist, key=lambda x: x[1]) )
or
map(lambda x: max(x, key=lambda y: y[1]) , lists)
As spintheblack says, you have a list of lists of tuples. I presume you are looking for the highest integer value of all tuples.
You can iterate over the outer list, then over the list of tuples tuples like this:
max_so_far = 0
for list in adymlist:
for t in list:
if t[1] > max_so_far:
max_so_far = t[1]
print max_so_far
This is a little bit more verbose but might be easier to understand.

Categories