Optimization of data input - python

I have an array whose elements I would like to increment when a new user votes.
For example if there are 10 options, from 1 to 10 and one user voted i=3 it would be easy to write:
A[i] = A[i] + 1;
In the case where the options are from 'A' to 'I', how can I do this? Because I can't use the letter to point to a specific array element.
For a few thousand users, I don't want to do an embedded loop where I search all elements of the array to see to which one the choice 'i' corresponds to each time.
Can I do this in O(n) time?

Is as simple as using dictionaries, a dictionary is like an array where instead of having index you have a key and for each key there is a value. For more information visit https://www.tutorialspoint.com/python/python_dictionary.htm
So in your example just define a dictionary like this:
data = {'A': 0, 'B': 0, 'C': 0 .....}
then find the letter that you want to upvote and increase it:
data['A'] += 1
print(data['A'])
>>> {'A': 1, 'B': 0, 'C': 0}
Even you can have dictionaries inside dictionaries, example:
data = {'A': {'Votes':0, 'Description': ''}, 'B': {'Votes':0, 'Description': ''}, 'C': {'Votes':0, 'Description': ''} .....}
data['A']['Votes'] += 1

Related

Is there a way to store values in one dictionary key that has multiple optional values?

I want to do something like this:
my_dict = {
('a'|'b'|'c') : 1
}
Clearly, this doesn't work but I was wondering if there are ways around it that are the same or more efficient than writing each out:
my_dict = {
'a' : 1,
'b' : 1,
'c' : 1
}
Any ideas?
You can create a dictionary with multiple keys all mapping to the same value using dict.fromkeys.
The first argument is a sequence of keys; the second argument is the value.
>>> dict.fromkeys('abc', 1)
{'a': 1, 'b': 1, 'c': 1}
'abc' works as a sequence of keys because in this case all your keys are strings of one character. More generally you can use a tuple or a list:
>>> dict.fromkeys(['a','b','c'], 1)
{'a': 1, 'b': 1, 'c': 1}
(N.B. creating a dict this way might cause problems if your value was mutable, since all the keys would reference the same value object.)
Create a dictionary with 3 keys, all with the value 1:
x = ('a', 'b', 'c')
y = 1
thisdict = dict.fromkeys(x, y)
print(thisdict)

Create dictionary with alphabet characters mapping to numbers

I want to write a code in Python, which assigns a number to every alphabetical character, like so: a=0, b=1, c=2, ..., y=24, z=25. I personally don't prefer setting up conditions for every single alphabet, and don't want my code look over engineered. I'd like to know the ways I can do this the shortest (meaning the shortest lines of code), fastest and easiest.
(What's on my mind is to create a dictionary for this purpose, but I wonder if there's a neater and better way).
Any suggestions and tips are in advance appreciated.
You definitely want a dictionary for this, not to declare each as a variable. A simple way is to use a dictionary comprehension with string.ascii_lowercase as:
from string import ascii_lowercase
{v:k for k,v in enumerate(ascii_lowercase)}
# {'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 5...
Here's my two cents, for loop will do the work:
d = {} #empty dictionary
alpha = 'abcdefghijklmnopqrstuvwxyz'
for i in range(26):
d[alpha[i]] = i #assigns the key value as alphabets and corresponding index value from alpha string as the value for the key
print(d) #instant verification that the dictionary has been created properly
One-liner with map and enumerate:
# given
foo = 'abcxyz'
dict(enumerate(foo))
# returns: {0: 'a', 1: 'b', 2: 'c', 3: 'x', 4: 'y', 5: 'z'}
If you needed it with the characters as the dictionary keys, what comes into my mind is either a dict comprehension...
{letter:num for (num,letter) in enumerate(foo) }
# returns {'a': 0, 'b': 1, 'c': 2, 'z': 3, 'y': 4, 'x': 5}
... or a lambda...
dict( map(lambda x: (x[1],x[0]), enumerate(foo)) )
# returns {'a': 0, 'b': 1, 'c': 2, 'z': 3, 'y': 4, 'x': 5}
I feel dict comprehension is much more readable than map+lambda+enumerate.
There are already numbers associated with characters. You can use these code points with ord().
A short (in terms of lines) solution would be:
num_of = lambda s: ord(s) - 97
A normal function would be easier to read:
def num_of(s):
return ord(s) - 97
Usage:
num_of("a") # 0
num_of("z") # 25
If it must be a dictionary you can create it without imports like that:
{chr(n):n-97 for n in range(ord("a"), ord("z")+1)}

Is there a way to randomly shuffle keys and values in a Python Dictionary, but the result can't have any of the original key value pairs?

I would like to shuffle the key value pairs in this dictionary so that the outcome has no original key value pairs. Starting dictionary:
my_dict = {'A':'a',
'K':'k',
'P':'p',
'Z':'z'}
Example of unwanted outcome:
my_dict_shuffled = {'Z':'a',
'K':'k', <-- Original key value pair
'A':'p',
'P':'z'}
Example of wanted outcome:
my_dict_shuffled = {'Z':'a',
'A':'k',
'K':'p',
'P':'z'}
I have tried while loops and for loops with no luck. Please help! Thanks in advance.
Here's a fool-proof algorithm I learned from a Numberphile video :)
import itertools
import random
my_dict = {'A': 'a',
'K': 'k',
'P': 'p',
'Z': 'z'}
# Shuffle the keys and values.
my_dict_items = list(my_dict.items())
random.shuffle(my_dict_items)
shuffled_keys, shuffled_values = zip(*my_dict_items)
# Offset the shuffled values by one.
shuffled_values = itertools.cycle(shuffled_values)
next(shuffled_values, None) # Offset the values by one.
# Guaranteed to have each value paired to a random different key!
my_random_dict = dict(zip(shuffled_keys, shuffled_values))
Disclaimer (thanks for mentioning, #jf328): this will not generate all possible permutations! It will only generate permutations with exactly one "cycle". Put simply, the algorithm will never give you the following outcome:
{'A': 'k',
'K': 'a',
'P': 'z',
'Z': 'p'}
However, I imagine you can extend this solution by building a random list of sub-cycles:
(2, 2, 3) => concat(zip(*items[0:2]), zip(*items[2:4]), zip(*items[4:7]))
A shuffle which doesn't leave any element in the same place is called a derangement. Essentially, there are two parts to this problem: first to generate a derangement of the keys, and then to build the new dictionary.
We can randomly generate a derangement by shuffling until we get one; on average it should only take 2-3 tries even for large dictionaries, but this is a Las Vegas algorithm in the sense that there's a tiny probability it could take a much longer time to run than expected. The upside is that this trivially guarantees that all derangements are equally likely.
from random import shuffle
def derangement(keys):
if len(keys) == 1:
raise ValueError('No derangement is possible')
new_keys = list(keys)
while any(x == y for x, y in zip(keys, new_keys)):
shuffle(new_keys)
return new_keys
def shuffle_dict(d):
return { x: d[y] for x, y in zip(d, derangement(d)) }
Usage:
>>> shuffle_dict({ 'a': 1, 'b': 2, 'c': 3 })
{'a': 2, 'b': 3, 'c': 1}
theonewhocodes, does this work, if you don't have a right answer, can you update your question with a second use case?
my_dict = {'A':'a',
'K':'k',
'P':'p',
'Z':'z'}
while True:
new_dict = dict(zip(list(my_dict.keys()), random.sample(list(my_dict.values()),len(my_dict))))
if new_dict.items() & my_dict.items():
continue
else:
break
print(my_dict)
print(new_dict)

How do I append a dictionary as another value to an existing dictionary key

I currently have a nested dictionary, with a dictionary as a value
I want to add another dictionary as SECOND item to the same key
so that it looks something like this:
{'mykey1': {'-11111': 0, 'A': 1}, {Second dictionary}, ...}
"append" doesn't work and "update" replaces the value.
Do I need something like a list of dictionaries for the value?
{'mykey1': [{'-11111': 0, 'A': 1}, {'-11111': 201910, 'A': 201910}] ,
'mykey2': [{'-11111': 0, 'A': 1}, {'-11111': 201909, 'A': 201910}]}
In which case:
a) How do I append the second dictionary element to each key in the existing dict?
b) How do I access that second dictionary?
thanks
you just need to build each object in turn.
first_dict{key}.update(list(first_dict{key}, {second_dict}.
will take the existing value from the dictionary for a given key and replace it with a list of that value plus another dictionary, second_dict
It isn't totally clear to me what how you want to structure your data.
If you built a little example of exactly what you want the data to be structured as, it'll be easier to give an exact answer.
Yes you need a list or a tuple for your Task. try to store the two dictionaries in a list and then assign it to the wrapper dictionary
ls = [{'-11111': 0, 'A': 1},{'-11111': 201910, 'A': 201910} ]
dic = {}
dic["myKey1"] = ls
or simply:
ls = [{'-11111': 0, 'A': 1},{'-11111': 201910, 'A': 201910} ]
dic = {"mykey": ls}
print(dic) # {'mykey': [{'-11111': 0, 'A': 1}, {'-11111': 201910, 'A': 201910}]}

How can i know the number of elements in a dictionary?

I know that len(dict) would give the number of keys but what i want is this
mydict = {
'a': [[2,4], [5,6]],
'b': [[1,1], [1,7,9], [6,2,3]],
'c': [['a'], [4,5]],
}
The number i want in this case is 7, 7 being the number of elements in 'a' + number of elements in 'b' + number of elements in 'c'
Given a dictionary
mydict = {
'a': [[2,4], [5,6]],
'b': [[1,1], [1,7,9], [6,2,3]],
'c': [['a'], [4,5]],
}
You can get the sum of the lengths of each value using
sum(map(len, mydict.values()))
Please correct your example, it is not valid python dict.
I assumed that against every key you have list of lists.
dict = {
'a': [[2,4],[5,6]],
'b': [[1,1],[1,7,9],[6,2,3]],
'c': [[3],[4,5]]
}
Your answer:
print sum (len(element) for element in dict.values());
Your code is not a valid python dictionary.
This is a valid dictionary:
dict = {
'a': ([2,4],[5,6]),
'b': ([1,1],[1,7,9],[6,2,3]),
'c': ([a],[4,5])
}
Use tuples to group multi-value items with fixed size (they have better performance than lists).
The answer to the question, using the correct dictionary, is
sum([len(e) for e in dict.values()])

Categories

Resources