This question already has answers here:
How can I make a dictionary (dict) from separate lists of keys and values?
(21 answers)
Closed last year.
Trying to make dictionary with 2 list one being the key and one being the value but I'm having a problem. This is what I have so far:
d={}
for num in range(10):
for nbr in range(len(key)):
d[num]=key[nbr]
Say my key is a list from 1 to 9, and value list is [2,4,0,9,6,6,8,6,4,5].
How do I assign so it that its like {0:2, 1:4, etc...}?
zip() to the rescue!
>>> k = range(1,10) # or some list or iterable of sorts
>>> v = [2,4,0,9,6,6,8,6,4,5]
>>> d = dict(zip(k,v))
>>> d
{1: 2, 2: 4, 3: 0, 4: 9, 5: 6, 6: 6, 7: 8, 8: 6, 9: 4}
>>>
For more details, see zip() built-in function, in Python documentation.
Note, regarding range() and the list of "keys".
The question reads "key is a list from 1 to 9" (i.e. 9 distinct keys) but the value list shows 10 distinct values. This provides the opportunity to discuss two points of "detail":
the range() function in the snippet above will produce the 1 through 9 range, that is because the starting value (1, here), if provided, is always included, whereas the ending value (10, here) is never included.
the zip() function stops after the iteration which includes the last item of the shortest iterable (in our case, omitting '5', the last value of the list)
If you are mapping indexes specifically, use the enumerate builtin function instead of zip/range.
dict(enumerate([2,4,0,9,6,6,8,6,4,5]))
values = [2,4,0,9,6,6,8,6,4,5]
d = dict(zip(range(10), values))
mydict = dict(zip(range(10), [2,4,0,9,6,6,8,6,4,5]))
should be something like
dict(zip(a,b))
Related
I want to filter even and odd values from a dictionary. I tried to add these even and odd values to lists but I keep getting empty output, why? My code is like this:
def Split(Dic1):
even = [ele for ele in Dic1.values() if ele is 2 ==0]
odd = [ele for ele in Dic1.values() if ele is 2 !=0]
print("Even lists:", even)
print("Odd lists:", odd)
Dic1 = {"N1": [1, 3, 7, 6, 10],
"N2": [2, 3, 9, 10, 21, 36],
"N3": [4, 6, 5, 12, 24, 35],
"N4": [0, 3, 14, 15, 16, 18]
}
Split(Dic1)
output:
Even lists: []
Odd lists: []
ele is 2 == 0 is really not at all the correct way to express this. The is operator checks whether two variables refer to the same object; comparing this truth value (True or False) to 0 is basically if False == False but that's obviously not what you are trying to check for.
The operator to check whether something is divisible evenly is called modulo and in Python it is spelled %.
Traversing the input list twice seems inelegant; you probably should just loop once, and pick out which new list to copy each value to.
Your function should not attempt to modify global variables. Instead, make it return two new lists, and have the caller decide what to do with the result (here, print it).
Your input dictionary's values() are not numbers so you can't use them directly in a loop. Either split out individual values for each key, or change the function to expect a list of lists from values().
Probably don't use Proper Case for function names; the Python convention is to capitalize class names, but use snake_case for regular functions and variables.
def even_odd_split(Dic1):
even = []
odd = []
for sublist in Dic1.values():
for ele in sublist:
if ele % 2 == 0:
even.append(ele)
else:
odd.append(ele)
return even, odd
print('Even items: %s\nOdd items%s' % even_odd_split(Dic1))
Perhaps notice that % is also - somewhat confusingly - a formatting operator when its first argument is a string. This is an example of operator overloading; though modern Python would perhaps prefer that you use .format() or an f-string here.
This question already has an answer here:
Python, TypeError: unhashable type: 'list'
(1 answer)
Closed 2 years ago.
# this doesn't work
invalid_dict = {[1, 5]: 'a', 5: 23}
# but this does
valid_dict = {(1, 5): 'a', 5: [23, 6]}
print(valid_dict)
I want to know what's the issue with invalid_dict that it doesn't work.
I understand that a hash value is computed for each item in a dictionary for storing the key-value pair at that location in the memory. But it seems strange to me that hash value for the the tuple (1,5) can be computed but not for the list [1,5].
Because tuple (1, 5) is passed by value and list [1,5] by reference.
There is no technical reasons for Python no to index by list but such strict behavior prevents lots of different confusions and post probably is faster.
Imagine this code:
k = [1,5]
d = {k: 7}
print d[k] # returns 7
k.append(6)
print d[k] # what should be returned here? 7 because we put by k or nothing because we put by [1,5] and now it’s [1,5,6]?
Developers should not be confused by such cases.
It’s not the case with tuple because it’s passed as a copy and you have no access to modify copy that was passed to func or indexer statement.
Say I'm receiving a list of arbitrary numbers from input, like
[1,2,3,4,5,6,7,8,8,9,10]
My code doesn't know what numbers these are going to be before it receives the list, and I want to return the number that appears twice automatically. How do I go about doing so?
Thank you.
You could do:
input = [1,2,3,4,5,6,7,8,8,9,10]
list_of_duplicates = []
for i in input:
if i not in list_of_duplicates:
list_of_duplicates.append(i)
input.pop(i)
print(input)
Now input will have all the numbers that were in the list multiple times.
You can use Counter By defualt Method in python 2 and 3
from collections import Counter
lst=[1,2,3,4,5,6,7,8,8,9,10]
items=[k for k,v in Counter(lst).items() if v==2]
print(items)
Hope this helps.
input = [1,2,3,4,5,6,7,8,8,9,10]
unique = set(input)
twice = []
for item in unique:
if input.count(item) == 2:
twice.append(item)
I've created something monstrous that does it in one line because my brain likes to think when it's time for bed I guess?
This will return a list of all duplicate values given a list of integers.
dupes = list(set(map(lambda x: x if inputList.count(x) >= 2 else None, inputList))-set([None]))
How does it work? The map() function applies a function every value of a list, in your case our input list with possible duplicates is called "inputList". It then applies a lambda function that returns the value of the integer being iterated over IF the iterated value when applied to the inputList via the .count() method is greater than or equal to two, else if it doesn't count as a duplicate it will return None. With this lambda function being applied by the map function, we get a list back that contains a bunch of None's and the actual integers detected as duplicates via the lambda function. Given that this is a list, we the use set to de-duplicate it. We then minus the set of duplicates against a static set made from a list with one item of None, stripping None values from our set of the map returned list. Finally we take the set after subtraction and convert it to a list called "dupes" for nice and easy use.
Example usage...
inputList = [1, 2, 3, 4, 4, 4, 5, 6, 6, 7, 1001, 1002, 1002, 99999, 100000, 1000001, 1000001]
dupes = list(set(map(lambda x: x if inputList.count(x) >= 2 else None, inputList))-set([None]))
print(dupes)
[1000001, 1002, 4, 6]
I'll let someone else elaborate on potential scope concerns..... or other concerns......
This will create a list of the numbers that are duplicated.
x = [1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 10]
s = {}
duplicates = []
for n in x:
try:
if s[n]:
duplicates.append(n)
s[n] = False
except KeyError:
s[n] = True
print(duplicates)
Assuming the list doesn't contain 0
I have a list:
input = ['a','b','c','a','b','d','e','d','g','g']
I want index of all elements except duplicate in a list.
output = [0,1,2,5,6,8]
You should iterate over the enumerated list and add each element to a set of "seen" elements and add the index to the output list if the element hasn't already been seen (is not in the "seen" set).
Oh, the name input overrides the built-in input() function, so I renamed it input_list.
output = []
seen = set()
for i,e in enumerate(input_list):
if e not in seen:
output.append(i)
seen.add(e)
which gives output as [0, 1, 2, 5, 6, 8].
why use a set?
You could be thinking, why use a set when you could do something like:
[i for i,e in enumerate(input_list) if input_list.index(e) == i]
which would work because .index returns you the index of the first element in a list with that value, so if you check the index of an element against this, you can assert that it is the first occurrence of that element and filter out those elements which aren't the first occurrences.
However, this is not as efficient as using a set, because list.index requires Python to iterate over the list until it finds the element (or doesn't). This operation is O(n) complexity and since we are calling it for every element in input_list, the whole solution would be O(n^2).
On the other hand, using a set, as in the first solution, yields an O(n) solution, because checking if an element is in a set is complexity O(1) (average case). This is due to how sets are implemented (they are like lists, but each element is stored at the index of its hash so you can just compute the hash of an element and see if there is an element there to check membership rather than iterating over it - note that this is a vague oversimplification but is the idea of them).
Thus, since each check for membership is O(1), and we do this for each element, we get an O(n) solution which is much better than an O(n^2) solution.
You could do a something like this, checking for counts (although this is computation-heavy):
indexes = []
for i, x in enumerate(inputlist):
if (inputlist.count(x) == 1
and x not in inputlist[:i]):
indexes.append(i)
This checks for the following:
if the item appears only once. If so, continue...
if the item hasn't appeared before in the list up till now. If so, add to the results list
In case you don't mind indexes of the last occurrences of duplicates instead and are using Python 3.6+, here's an alternative solution:
list(dict(map(reversed, enumerate(input))).values())
This returns:
[3, 4, 2, 7, 6, 9]
Here is a one-liner using zip and reversed
>>> input = ['a','b','c','a','b','d','e','d','g','g']
>>> sorted(dict(zip(reversed(input), range(len(input)-1, -1, -1))).values())
[0, 1, 2, 5, 6, 8]
This question is missing a pandas solution. 😉
>>> import pandas as pd
>>> inp = ['a','b','c','a','b','d','e','d','g','g']
>>>
>>> pd.DataFrame(list(enumerate(inp))).groupby(1).first()[0].tolist()
[0, 1, 2, 5, 6, 8]
Yet another version, using a side effect in a list comprehension.
>>> xs=['a','b','c','a','b','d','e','d','g','g']
>>> seen = set()
>>> [i for i, v in enumerate(xs) if v not in seen and not seen.add(v)]
[0, 1, 2, 5, 6, 8]
The list comprehension filters indices of values that have not been seen already.
The trick is that not seen.add(v) is always true because seen.add(v) returns None.
Because of short circuit evaluation, seen.add(v) is performed if and only if v is not in seen, adding new values to seen on the fly.
At the end, seen contains all the values of the input list.
>>> seen
{'a', 'c', 'g', 'b', 'd', 'e'}
Note: it is usually a bad idea to use side effects in list comprehension,
but you might see this trick sometimes.
I'd like to create a function that will print the sum and the position of the maximum value within a list of numbers, but I'm not sure how to go about doing so.. This is what I've started with so far:
I used some code off a similar question that was asked.
def maxvalpos(variables):
max = 0
for i in range(len(variables)):
if variables[i] > max:
max = variables[i]
maxIndex = i
return (max, maxIndex)
print maxvalpos(4, 2, 5, 10)
When I run this code it just returns that the function can only take 1 argument. Thank you.
Then give it one argument, or modify the definition.
print maxvalpos([4, 2, 5, 10])
or
def maxvalpos(*variables):
The pythonic way of doing this:
my_list_sum=sum(my_list)
index_max=my_list.index(max(my_list))
This finds the sum of the list and the index of the maximum of the list
But the problem in your code is: You are sending four variables to the function and receiving only 1 variable. For that to work, use:
maxvalpos([4,2,7,10])
This sends only one argument, a list to the function
An easier way to do this
>>> from operator import itemgetter
>>> maxpos, maxval = max(enumerate(my_list), key=itemgetter(1))
eg.
>>> max(enumerate([4, 2, 5, 10]), key=itemgetter(1))
(3, 10)