Python 3 - Dynamic Expression Evaluation - python-3.x

I am trying to figure out the syntax for evaluation an expression in Python that involves substituting a variable.
The code needs to go through a list of options, insert string input within the "{:(insert list item here)}"
Example Code (Python 3.x):
n = 11
print("my number is {:d}".format(n))
formatList = ['e', 'b', 'o', 'd', 'x', 'f', 's']
for atype in formatList:
# Failed Attempts:
# print("my number is {:eval(atype)}".format(n))
# print("my number is {:" + eval(atype) + "}".format(n))
# print(eval("my number is {:" + atype + "}").format(n))
# print(eval(' "my number is {:" + atype + "}".format(n)) '))
The output should resemble the number 11, in all the possible formats given by the list.
Thank you for everyones help!

You can achieve this by splitting in two passages:
n = 11
print("my number is {:d}".format(n))
formatList = ['e', 'b', 'o', 'd', 'x', 'f', 's']
for atype in formatList:
str_template = 'my number is {:' + atype + '}'
print(str_template.format(n))
If you really want one line, you can use this answer, to have a literal curly bracket in the string, by using double curly brackets '{{':
for atype in formatList:
print('my number is {{:{}}}'.format(atype).format(n))

Related

How do I iterate through a list by the indices of a different list?

I want sub_main to be made from the 'sub' list as:
sub_main = ['c','d','e','f','j','k','l','m','n','o','p'...
I have tried:
for i in sub:
for j in main:
if j == i[0]:
while j != i[1]:
sub_main.append(j)
but it is an infinite loop for some reason
import string
sub_main = []
main = list(string.ascii_lowercase)
sub = [['c','f'],['j','p'],['r','t']]
import string
sub_main = []
main = list(string.ascii_lowercase)
sub = [['c', 'f'], ['j', 'p'], ['r', 't']]
indexed_main = {ch: i for i, ch in enumerate(main)}
for s in sub:
sub_main.extend(main[indexed_main[s[0]]:indexed_main[s[1]]+1])
import string
sub_main = []
main = list(string.ascii_lowercase)
sub = [['c','f'],['j','p'],['r','t']]
for chsub in sub:
amount = ord(chsub[1]) - ord(chsub[0])
remaining = amount
while remaining >= 0:
sub_main.append(main[ord(chsub[0])-ord('a') + amount - remaining])
remaining -= 1
This is how I would have done it, it uses the fact that every character has an ascii value.
Basically iterate over each sub-list in sub and get the amount of characters that are between the two in chsub.
main[ord(chsub[0])-ord('a') + amount - remaining] - This first finds the index of the character it should be on (c - a, for example, which is 2 which means it begins from main[2]).
Then inside that calculation I also check the difference between amount and remaining to see which character it needs to get past the initial character.
Result:
['c', 'd', 'e', 'f', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'r', 's', 't']
The reason for your infinite loop has been given in a comment to your question, you never change j in the while, but 3 loops is too much for this issue.

Based on a condition perform reranking of elements in the list in python

i have a ranked list of elements as below :
ranked_list_1 = ['G','A','M','S','D']
i need to rerank the list as below
1) Re rank as :
re_ranked_list_1 = ['A','M','D','E','G','S']
Logic : 'G' and 'S' should always be in last 2 positions and new element 'E' should also be tagged to the list just before the last 2 position.
I think this is what you want. This will put 'G' and 'S' at the end, in the order they appear in the list.
ordered_list = list()
final_terms = ['E']
for item in ranked_list_1:
if item in ['G', 'S']:
final_terms.append(item)
else:
ordered_list.append(item)
output_list = ordered_list + final_terms
print(output_list)
>>>['A', 'M', 'D', 'E', 'G', 'S']

Getting all str type elements in a pd.DataFrame

Based on my little knowledge on pandas,pandas.Series.str.contains can search a specific str in pd.Series. But what if the dataframe is large and I just want to glance all kinds of str element in it before I do anything?
Example like this:
pd.DataFrame({'x1':[1,2,3,'+'],'x2':[2,'a','c','this is']})
x1 x2
0 1 2
1 2 a
2 3 c
3 + this is
I need a function to return ['+','a','c','this is']
If you are looking strictly at what are string values and performance is not a concern, then this is a very simple answer.
df.where(df.applymap(type).eq(str)).stack().tolist()
['a', 'c', '+', 'this is']
There are 2 possible ways - check numeric values saved as strings or not.
Check difference:
df = pd.DataFrame({'x1':[1,'2.78','3','+'],'x2':[2.8,'a','c','this is'], 'x3':[1,4,5,4]})
print (df)
x1 x2 x3
0 1 2.8 1
1 2.78 a 4 <-2.78 is float saved as string
2 3 c 5 <-3 is int saved as string
3 + this is 4
#flatten all values
ar = df.values.ravel()
#errors='coerce' parameter in pd.to_numeric return NaNs for non numeric
L = np.unique(ar[np.isnan(pd.to_numeric(ar, errors='coerce'))]).tolist()
print (L)
['+', 'a', 'c', 'this is']
Another solution is use custom function for check if possible convert to floats:
def is_not_float_try(str):
try:
float(str)
return False
except ValueError:
return True
s = df.stack()
L = s[s.apply(is_not_float_try)].unique().tolist()
print (L)
['a', 'c', '+', 'this is']
If need all values saved as strings use isinstance:
s = df.stack()
L = s[s.apply(lambda x: isinstance(x, str))].unique().tolist()
print (L)
['2.78', 'a', '3', 'c', '+', 'this is']
You can using str.isdigit with unstack
df[df.apply(lambda x : x.str.isdigit()).eq(0)].unstack().dropna().tolist()
Out[242]: ['+', 'a', 'c', 'this is']
Using regular expressions and set union, could try something like
>>> set.union(*[set(df[c][~df[c].str.findall('[^\d]+').isnull()].unique()) for c in df.columns])
{'+', 'a', 'c', 'this is'}
If you use a regular expression for a number in general, you could omit floating point numbers as well.

how to allow user input both str and int [duplicate]

This question already has answers here:
converting individual digits to string
(4 answers)
Closed 7 years ago.
I have a function that is supposed to take a user input both string and int such as (555-GOT-FOOD) and print the correct digit for each string character. How can i get my function to take the user input (555-GOT-EATS)
Code:
def num(n):
chars = []
for char in n:
if char.isalpha():
if char.lower() in ['A', 'B', 'C']:
chars.append('2')
elif char.lower() in ['D', 'E', 'F']:
chars.append('3')
elif char.lower() in ['G', 'H', 'I']:
chars.append('4')
elif char.lower() in ['J', 'K', 'L']:
chars.append('5')
elif char.lower() in ['M', 'N', 'O']:
chars.append('6')
elif char.lower() in ['P', 'R', 'S']:
chars.append('7')
elif char.lower() in ['T', 'U', 'V']:
chars.append('8')
else:
chars.append('9')
else:
chars.append(char)
return ''.join(chars)
num (555-"got"-"food")
Either you take in a char array and convert the first three numbers in to an int afterwards. Alternatlively you can take in a string and after pull out the 3numbers and convert to an int.
If you are getting user input, you shouldn't need to worry about the 5's being ints because they aren't ints! Python gets all user input as a string. So they are numbers, yes, but they are of the type string, not int. Think of them as just the symbols representing numbers.
If you modify the end of your code like this, it should work.
elif char.lower() in ['T', 'U', 'V']:
chars.append('8')
elif char.lower() in ['X', 'Y', 'Z']:
chars.append('9')
else:
chars.append(char)
return ''.join(chars)
You will also want to use
n.replace("-", "")
to get rid of all "-", giving you "555GOTFOOD" instead of "555-GOT-FOOD".
Also, I'm not sure if it will work as is, or if you need to change char.lower() to char.upper() since your lists are all upper case letters.

Musical note string (C#-4, F-3, etc.) to MIDI note value, in Python

The code in my answer below converts musical notes in strings, such as C#-4 or F-3, to their corresponding MIDI note values.
I am posting this because I am tired of trying to dig it up online every time I need it. I'm sure I'm not the only one who can find a use for it. I just wrote this up — it is tested and correct. It's in Python, but I feel that it pretty close to universally understandable.
#Input is string in the form C#-4, Db-4, or F-3. If your implementation doesn't use the hyphen,
#just replace the line :
# letter = midstr.split('-')[0].upper()
#with:
# letter = midstr[:-1]
def MidiStringToInt(midstr):
Notes = [["C"],["C#","Db"],["D"],["D#","Eb"],["E"],["F"],["F#","Gb"],["G"],["G#","Ab"],["A"],["A#","Bb"],["B"]]
answer = 0
i = 0
#Note
letter = midstr.split('-')[0].upper()
for note in Notes:
for form in note:
if letter.upper() == form:
answer = i
break;
i += 1
#Octave
answer += (int(midstr[-1]))*12
return answer
NOTES_FLAT = ['C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B']
NOTES_SHARP = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']
def NoteToMidi(KeyOctave):
# KeyOctave is formatted like 'C#3'
key = KeyOctave[:-1] # eg C, Db
octave = KeyOctave[-1] # eg 3, 4
answer = -1
try:
if 'b' in key:
pos = NOTES_FLAT.index(key)
else:
pos = NOTES_SHARP.index(key)
except:
print('The key is not valid', key)
return answer
answer += pos + 12 * (int(octave) + 1) + 1
return answer

Resources