int() or dict for single digit string to int conversions - python-3.x

I am trying to convert a single-digit string to an integer. For example, if I have "2" <-- str I want to change it to 2 <-- int. I know that the int() function in python can do this for me, but I want to know if I made a dictionary like this,
strToNumDict{
"0": 0
"1": 1
"2": 2
"3": 3
"4": 4
"5": 5
"6": 6
"7": 7
"8": 8
"9": 9
}
Would using this dictionary to convert single digits be faster than the int() function? And if one is faster, is it fast enough to make a difference on which one I should use?

Let's do a quick timeit benchmark. We generate at random one digit and will try to convert it to integer (x 1_000_000 times):
strToNumDict = {
"0": 0,
"1": 1,
"2": 2,
"3": 3,
"4": 4,
"5": 5,
"6": 6,
"7": 7,
"8": 8,
"9": 9
}
def convert1(s):
return strToNumDict[s]
def convert2(s):
return int(s)
import timeit
import random
digits = list('0123456789')
t1 = timeit.timeit(lambda: convert1(random.choice(digits)), number=1_000_000)
t2 = timeit.timeit(lambda: convert2(random.choice(digits)), number=1_000_000)
print(t1)
print(t2)
Prints on my machine (AMD 2400G, Python 3.6.8):
0.6220340259897057
0.727682675991673
So dict-based version is marginally faster in this case. Personally, not worth the effort. With int() you get conversion from negative numbers, more than number 9 etc. And it's more readable.

Related

How do I count the amount of 'edges' in a word in Python, using a dictionary?

For this exercise I need to count the 'number of edges' in the word 'AARDGASRESERVES' (Dutch), using a for loop and a dictionary. I already have the following code, but this doesn't give me the required output (which should be 31). I believe the middle part isn't quite right yet.
# dictionary of number of edges per letter
edges = {"A": 2, "R": 2, "D": 0,"G": 2,"S": 2,"R": 2,"E": 3, "V": 2}
word = "AARDGASRESERVES"
# loop over the letters in the word and count the number of edges
total_edges = 0
for key in edges:
if edges[key] == word:
total_edges += [value]
# print the total
print("Total number of edges:", total_edges)
I tried if edges[key] in word: too but that results in an error. I'm still new to Python so I might have written something that isn't even possible.
A simple way to do what you want is:
edges = {"A": 2, "R": 2, "D": 0,"G": 2,"S": 2,"R": 2,"E": 3, "V": 2}
word = "AARDGASRESERVES"
total_edges = sum([edges[c] for c in word])
# print the total
print("Total number of edges:", total_edges) # Output: 31
However, I advise you to carefully examine your code to understand why it doesn't work. For example here:
...
if edges[key] == word:
...
you compare if a number (value of your dict) is equal to the whole word, which is an irrational if-statement.
From what I understand about the purpose of this code. It should go about this
# dictionary of number of edges per letter
edges = {"A": 2, "R": 2, "D": 0,"G": 2,"S": 2,"R": 2,"E": 3, "V": 2}
word = "AARDGASRESERVES"
# loop over the letters in the word and count the number of edges
total_edges = 0
for key in word:
total_edges += edges[key]
# print the total
print("Total number of edges:", total_edges)
What you want to do is to get a letter from the word and get the specific element associated with that key and add it.

Find the intersection of dict of dicts based on the rules in python3.x

I have two dictionaries as given below and want to find the intersection of dictionaries based on some logic.
dict1= {"1":{"score1": 1.099, "score2":0.45},
"2": {"score2": 0.099, "score3":1.45},
"3": {"score2": 10, "score3":10.45}}
dict2= {"1":{"score6": 1.099, "score2":0.45},
"2": {"score2": 10, "score3":10.45},
"4": {"score5": 8, "score8":15}}
I want to create the dictionary based on the given two dictionaries based on the below rules:
1.union of the two dicitonaries based on the outer key
if outer key is common in both the dictionaries then in the nested key-value pair show only the common key with highest value across both the dictionaries.
result_dict = {"1":{"score2":0.45},
"3": {"score2": 10, "score3":10.45},
"2": {"score2": 10, "score3":10.45},
"4": {"score5": 8, "score8":15}}```
First off, thanks for providing concrete examples of what your inputs are like and what you'd like the output to look like.
There may well be more efficient ways of doing this, but since there's no mention of any constraints on performance, my first instinct was to turn to Python's set operations to make things a little simpler:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
dict1 = {
"1": {
"score1": 1.099,
"score2": 0.45
},
"2": {
"score2": 0.099,
"score3": 1.45
},
"3": {
"score2": 10,
"score3": 10.45
}
}
dict2 = {
"1": {
"score6": 1.099,
"score2": 0.45
},
"2": {
"score2": 10,
"score3": 10.45
},
"4": {
"score5": 8,
"score8": 15
}
}
result_dict = {
"1": {
"score2": 0.45
},
"3": {
"score2": 10,
"score3": 10.45
},
"2": {
"score2": 10,
"score3": 10.45
},
"4": {
"score5": 8,
"score8": 15
}
}
def weird_union(d1, d2):
"""Applies the logic in OP's question
Args:
d1 (dict): dict with one level of nested dicts as values
d2 (dict): dict with one level of nested dicts as values
Returns: dict
"""
result = {}
k1, k2 = set(d1.keys()), set(d2.keys())
# no collisions-- easy case
for k in k1.symmetric_difference(k2):
result[k] = d1[k] if k in d1 else d2[k]
# key appears in both dicts
for k in k1.intersection(k2):
_k1, _k2 = set(d1[k].keys()), set(d2[k].keys())
result[k] = {
key: max([d1[k][key], d2[k][key]])
for key in _k1.intersection(_k2)
}
return result
test = weird_union(dict1, dict2)
assert result_dict == test
print('Test passed.')
The basic idea is to treat the disjoint and the intersection cases separately. Hope this helps.
Update in response to comment:
In the future, please provide this sort of context up front; an operation on two dictionaries is rather different than an operation on an arbitrary number of inputs.
Here's one way to do it:
def invert_dicts(*dicts):
""" Takes multiple dicts and returns a dict mapping
key to dict index. E.g.,
invert_dicts(
{'a': 1, 'b': 2},
{'a': 3, 'c': 4}
)
returns
{'a': [0, 1], 'b': [0], 'c': [1]}
"""
key_map = {}
for i, d in enumerate(dicts):
for k in d.keys():
key_map.setdefault(k, []).append(i)
return key_map
def weird_n_union(*dicts):
"""Applies the logic in OP's question to an arbitrary number of inputs
>>> weird_n_union(d1, d2, ..., dn)
Args:
*dicts (dict): dictionaries w/one level of nested dicts as values
Returns: dict
"""
result = {}
# dict mapping key to list of dict index in `dicts` containing key
key_map = invert_dicts(*dicts)
for k in key_map:
# no outer key collision
if len(key_map[k]) == 1:
result[k] = dicts[key_map[k][0]][k]
# outer key collision
else:
# unclear what should happen in the case where:
# - there is an outer key collision
# - there are no shared sub-keys
#
# this implementation assumes that in that case, the value for k is {}
result.setdefault(k, {})
sub_dicts = tuple(dicts[i][k] for i in key_map[k])
# map keys in `sub_dicts` to indices for `dicts` containing key
sub_key_map = invert_dicts(*sub_dicts)
# contains elements of (k, v), where k appears in > 1 sub-dicts
shared_keys_only = filter(lambda kv: len(kv[1]) > 1,
sub_key_map.items())
# update result with the max value for each shared key
for kv in shared_keys_only:
max_ = max(((kv[0], sub_dicts[i][kv[0]]) for i in kv[1]),
key=lambda x: x[1])
result[k].update({max_[0]: max_[1]})
return result
Tried to annotate to make it a bit clear how things work. Hopefully this works for your use case.

How do i replace Numbers with letters using dictionaries in python

I have been developing an application to convert decimal numbers into hexadecimal ones. Whole software is done but the problem in i have to convert digits like "11", "12" into "B", "C".
For this, i made a dictionary but i don't know how to apply that into my software.
hexadecimal_value = {1: "1",
2: "2",
3: "3",
4: "4",
5: "5",
6: "6",
7: "7",
8: "8",
9: "9",
10: "A",
11: "B",
12: "C",
14: "D",
15: "E"}
while 1:
print("we are about to convert decimal numbers into hexadecimal
numbers.")
decision = input("type 'stop' to stop, type anything to Continue")
if decision != "stop":
try:
h = int(input("Enter an integer\n>"))
except ValueError:
print("This is not an integer, silly!")
h = int(input("Enter an integer\n>"))
lup = 1
hexadecimal_digits = []
while lup == 1:
hexa = h%16
hexadecimal_digits.append(str(hexa))
h = int(h/16)
if h<1:
lup = 2
def Reverse_hexa(hexadecimal_digits):
hexadecimal_digits.reverse()
return hexadecimal_digits
print("-".join(Reverse_hexa(hexadecimal_digits)))
if decision == "stop":
input("close:")
break
First of all because your dictionary uses int as keys, don't save the digits as strings, meaning: change the appending line to:
hexadecimal_digits.append(hexa)
Now you just need to translate the digits to the symbols using your dictionary:
hexadecimal_symbols = [hexadecimal_value[digit] for digit in hexadecimal_digits]
And now print those:
print("-".join(Reverse_hexa(hexadecimal_symbols)))
Alternatively, just save the translated symbols from the start:
hexadecimal_digits.append(hexadecimal_value[hexa])
And the rest stays the same
Just the following
hexadecimal_value[10]
Alternatively you don't need to declare a dictionary:
hex(10)
>>>'0xa'
and if you want just the capital letter:
hex(10).upper()[2:]

Pandas dataframe transpose with column name instead of index

I can't seem to figure out how to show actual column name in json after dataframe has been transposed. Any thoughts please?
from pandasql import *
import pandas as pd
pysqldf = lambda q: sqldf(q, globals())
q1 = """
SELECT
beef as beef, veal as veal, pork as pork, lamb_and_mutton as lamb
FROM
meat m
LIMIT 3;
"""
meat = load_meat()
df = pysqldf(q1)
#df = df.reset_index(drop=True)
#print(df.T.to_json(orient='records'))
df1 = df.T.reset_index(drop=True)
df1.columns = range(len(df1.columns))
print(df.T.to_json(orient='records'))
Output
[{"0":751.0,"1":713.0,"2":741.0},{"0":85.0,"1":77.0,"2":90.0},{"0":1280.0,"1":1169.0,"2":1128.0},{"0":89.0,"1":72.0,"2":75.0}]
Expected Output
[ { "0": "beef", "1": 751, "2": 713, "3": 741},{"0": "veal", "1": 85, "2": 77, "3": 90 },{"0": "pork", "1": 1280, "2": 1169, "3": 1128},{ "0": "lamb", "1": 89, "2": 72, "3": 75 }]
Try this:
Where df:
beef veal pork lamb
0 0 1 2 3
1 4 5 6 7
2 8 9 10 11
Use T, reset_index, and set_axis:
df.T.reset_index()\
.set_axis(range(len(df.columns)), axis=1, inplace=False)\
.to_json(orient='records')
Output:
'[{"0":"beef","1":0,"2":4,"3":8},{"0":"veal","1":1,"2":5,"3":9},{"0":"pork","1":2,"2":6,"3":10},{"0":"lamb","1":3,"2":7,"3":11}]'

converting individual digits to string

I think i'm very close but i cant seem to fix my issues. I need a function that takes a 10-digit input from user (me) and sets each letter to is numeric value.
Example: user inputs (941-019-abcd) the function should then take this and return (941-019-2223)
Anything that i should be doing differently please feel free to elaborate
Here is what i have thus far:
def main(phone_number):
digits = ["2", "3", "4", "5", "6", "7", "8", "9"]
numeric_phone=" "
ch = digits[i]
for ch in phone_number:
if ch.isalpha():
elif ch== 'A' or 'b' or 'c':
i=2
elif ch== 'd' or 'e' or 'f':
i=3
elif ch== 'g' or 'h' or 'i':
i=4
elif ch=='j' or 'k' or 'l':
i=5
elif ch== 'm' or 'n' or 'o':
i=6
elif ch== 'p' or 'r' or 's':
i=7
elif ch=='t' or 'u' or 'v':
i=8
else:
index=9
numeric_phone= numeric_phone+ch
print (numeric_phone)
phone_number = '941-019-aBcD'
# A map of what letters to convert to what digits.
# I've added q and wxy & z.
digit_map = {
'abc': 2,
'def': 3,
'ghi': 4,
'jkl': 5,
'mno': 6,
'pqrs': 7,
'tuv': 8,
'wxyz': 9
}
# Break this out into one letter per entry in the dictionary
# to make the actual work of looking it up much simpler.
# This is a good example of taking the data a person might
# have to deal with and making it easier for a machine to
# work with it.
real_map = {}
for letters, number in digit_map.iteritems():
for letter in letters:
real_map[letter] = number
# Empty new variable.
numeric_phone = ''
# For each character try to 'get' the number from the 'real_map'
# and if that key doesn't exist, just use the value in the
# original string. This lets existing numbers and other
# characters like - and () pass though without any special
# handling.
# Note the call to `lower` that converts all our letters to
# lowercase. This will have no effect on the existing numbers
# or other speacial symbols.
for ch in phone_number.lower():
numeric_phone += str(real_map.get(ch, ch))
print(numeric_phone)
def main(phone_number):
digits = ["2", "3", "4", "5", "6", "7", "8", "9"]
numeric_phone=" "
for ch in phone_number:
if ch.isalpha():
if ord(ch) >= 97:
ch = +2 (ord(ch)-97)/3
else:
ch = +2 (ord(ch)-65)/3
numeric_phone= numeric_phone+ch
print (numeric_phone)
Use ord() to convert chars to their ASCII values and then get the right number.
You can create a formula to ascertain the correct number to add depending on the letter:
math.ceil((index(char)+1)/3)
Use a list and depending on which character it is, append a number to the list. At the end, return the list, but joined so that it is a string:
def numerify(inp):
from math import ceil as _ceil
from string import lowercase as _lowercase
chars = []
for char in inp:
if char.isalpha():
num = _ceil((_lowercase.index(char)+1)/float(3))
chars.append(str(int(num+1)))
else:
chars.append(char)
return ''.join(chars)
>>> from numerify import numerify
>>> numerify('1')
'1'
>>> numerify('941-019-abcd')
'941-019-2223'
>>>
I think it's easiest to pre-calculate the number character for each letter.
# len(keys) == 26 so that the index of a letter
# maps to its phone key
keys = ['2']*3 + ['3']*3 \
+ ['4']*3 + ['5']*3 + ['6']*3 \
+ ['7']*4 + ['8']*3 + ['9']*4
def letter_to_key(x):
if x.isalpha():
# calculate the 'index' of a letter.
# a=0, b=1, ..., z=25
index = ord(x.lower()) - ord('a')
return keys[index]
# If it's not a letter don't change it.
return x
def translate_digits(phone_num):
return ''.join(map(letter_to_key, phone_num))
print(translate_digits('941-019-abcd'))

Resources