Align numbers right for any input? - python

I need to align numbers right for any input. However I can't seem to do it only for a specific input not for any input. I've also tried turning the list of strings into a list of nums using list comprehension and then do print("{:5d}".format(i)). I've also tried doing something like print("{:>len(i)}".format(i))
n = input().split()
m = sorted(n, key =int, reverse = True)
for i in m:
print("{:>10}".format(i))
Sample Input:
8 11 12 123 45678
Sample Output:
45678
123
12
11
8
I've managed to do it for the input above, but not for any input.

maybe it could generalize better by keeping your elements as strings and using rjust() ?
n = input().split()
for i in n:
print(i.rjust(len(max(n, key = len))))

You can use a variable width specifier in string formatting:
n = input().split()
l = max(len(i) for i in n)
m = sorted(n, key=int, reverse=True)
for i in m:
print("{:>{:d}}".format(i, l))
With an input of 1231231232131213 123123213213 12312321321 213123123, the output is:
1231231232131213
123123213213
12312321321
213123123

Related

Adding text in front of separate numbers in list

Im new to python and hit a wall with my last print in my program
I got a list of numbers created with math int(numbers that when printed looks like this
[0, 0, 0, 0] #just with random numbers from 1 - 1000
I want to add text in front of every random number in list and print it out like this
[Paul 0 Frederick 0 Ape 0 Ida 0]
Any help would be appreciated. Thanks !
Sounds like you want to make a dictionary. You could type:
d = dict()
d["Paul"] = random.randint(1,100)
....
print(d)
#output: {"Paul":1, "Fredrick":50, "Ape":25, "Ida":32}
Alternatively there is nothing stopping you from using strings and integers in the same list! Python is not strongly statically typed.
If you have a list of numbers [45,5,59,253] and you want to add names to them you probably need a loop.
nums = [45,5,59,253]
names = ["Paul", "Frederick", "Ape", "Ida"]
d = dict()
i = 0
for n in nums:
d[names[i]] = n
i+=1
or if you wanted a list
nums = [45,5,59,253]
names = ["Paul", "Frederick", "Ape", "Ida"]
list = [x for y in zip(names, nums) for x in y]
You'd have to turn your random integers into strings and add them to the text (string) you want.
Example:
lst=[]
x = str(randint(0,1000))
text = 'Alex'
final_text = text+' '+x
lst.append(final_text)
Just added the space like in your example. It'll just be a little more complex to access the numbers if you do it this way.

Select and store data from string in python

I got the information of a txt file and store it as lines
print(lines)
['>chr12_9180206_+:chr12_118582391_+:a1;2 total_counts: 115 Seed: 4 K: 20 length: 79\n', 'TTGGTTTCGTGGTTTTGCAAAGTATTGGCCTCCACCGCTATGTCTGGCTGGTTTACGAGC\n', 'AGGACAGGCCGCTAAAGTG\n', '>chr12_9180206_+:chr12_118582391_+:a2;2 total_counts: 135 Seed: 4 K: 20 length: 80\n', 'CTAACCCCCTACTTCCCAGACAGCTGCTCGTACAGTTTGGGCACATAGTCATCCCACTCG\n', 'GCCTGGTAACACGTGCCAGC\n']
If you execute the code
for i in lines:
print(i)
You get:
>chr12_9180206_+:chr12_118582391_+:a1;2 total_counts: 115 Seed: 4 K: 20 length: 79
TTGGTTTCGTGGTTTTGCAAAGTATTGGCCTCCACCGCTATGTCTGGCTGGTTTACGAGC
AGGACAGGCCGCTAAAGTG
>chr12_9180206_+:chr12_118582391_+:a2;2 total_counts: 135 Seed: 4 K: 20 length: 80
CTAACCCCCTACTTCCCAGACAGCTGCTCGTACAGTTTGGGCACATAGTCATCCCACTCG
GCCTGGTAACACGTGCCAGC
I want to store the sequences that are in caps TTGGTTTCGTGGTTT... as independent elements in an object so you can operate with them, so you would be able to do something like:
seq[1]
>>> TTGGTTTCGTGGTTTTGCAAAGTATTGGCCTCCACCGCTATGTCTGGCTGGTTTACGAGCAGGACAGGCCGCTAAAGTG
gattaca = [x.strip() for x in lines if x.isupper()]
>>> gattaca
['TTGGTTTCGTGGTTTTGCAAAGTATTGGCCTCCACCGCTATGTCTGGCTGGTTTACGAGC',
'AGGACAGGCCGCTAAAGTG',
'CTAACCCCCTACTTCCCAGACAGCTGCTCGTACAGTTTGGGCACATAGTCATCCCACTCG',
'GCCTGGTAACACGTGCCAGC']
You can do this:
lines = list(map(str.strip, (filter(str.isupper, lines))))
So if you use isupper() you can check if your string in the list is upper case. If True, it means it is.
for i in lines:
if i.isupper():
## store the string
To check wheter a string is caps I woult use mySting == mySting.upper().
To get all caps elements you could use a list comprehension like so:
result = [s for s in lines if lines == lines.upper()]
This would still allow special characters in your string.
If you only want uppercase leters then use lines.isalpha().
result = [s for s in lines if lines == lines.upper() and lines.isalpha()]
I would use a regex:
import re
seq={}
pattern=r'^(>.*$)\n([ACGTU\n]*?)(?=^>|\Z)'
for i,m in enumerate(re.finditer(pattern, ''.join(lines), flags=re.M)):
seq[i]=m.group(2).replace('\n','')
Then each FASTA seq is mapped to an integer:
>>> seq
{0: 'TTGGTTTCGTGGTTTTGCAAAGTATTGGCCTCCACCGCTATGTCTGGCTGGTTTACGAGCAGGACAGGCCGCTAAAGTG', 1: 'CTAACCCCCTACTTCCCAGACAGCTGCTCGTACAGTTTGGGCACATAGTCATCCCACTCGGCCTGGTAACACGTGCCAGC'}

Simpler / faster / more elegant way to split a string at custom positions

I've been searching for a simpler way to do this, but i'm not sure what search parameters to use. I have a floating point number, that i would like to round, convert to a string, then specify a custom format on the string. I've read through the .format docs, but can't see if it's possible to do this using normal string formatting.
The output i want is just a normal string, with spaces every three chars, except for the last ones, which should have a space four chars before the end.
For example, i made this convoluted function that does what i want in an inefficient way:
def my_formatter(value):
final = []
# round float and convert to list of strings of individual chars
c = [i for i in '{:.0f}'.format(value)]
if len(c) > 3:
final.append(''.join(c[-4:]))
c = c[:-4]
else:
return ''.join(c)
for i in range(0, len(c) // 3 + 1, 1):
if len(c) > 2:
final.insert(0, ''.join(c[-3:]))
c = c[:-3]
elif len(c) > 0:
final.insert(0, ''.join(c))
return(' '.join(final))
e.g.
>>> my_formatter(123456789.12)
>>> '12 345 6789'
>>> my_formatter(12345678912.34)
>>> '1 234 567 8912'
Would really appreciate guidance on doing this in a simpler / more efficient way.
Took a slightly different angle but this uses a third party function partition_all. In short, I use it to group the string into groups of 3 plus the final group if there are less than 3 chars. You may prefer this as there are no for loops or conditionals but it's basically cosmetic differences.
from toolz.itertoolz import partition_all
def simpleformat(x):
x = str(round(x))
a, b = x[:-4], x[-4:]
strings = [''.join(x[::-1]) for x in reversed(list(partition_all(3, a[::-1])))]
return ' '.join(strings + [b])
Try this:
def my_formatter(x):
# round it as text
txt = "{:.0f}".format(x)
# find split indices
splits = [None] + list(range(-4, -len(txt), -3)) + [None]
# slice and rejoin
return " ".join(
reversed([txt[i:j] for i, j in zip(splits[1:], splits[:-1])]))
Then
>>> my_formatter(123456789.1)
12 345 6789
>>> my_formatter(1123456789.1)
112 345 6789
>>> my_formatter(11123456789.1)
1 112 345 6789
Here is a pretty simple solution using a loop over the elements in the reverse order such that counting the indices is easier:
num = 12345678912.34
temp = []
for ix, c in enumerate(reversed(str(round(num)))):
if ix%3 == 0 and ix !=0: temp.extend([c, ' '])
else: temp.extend(c)
''.join(list(reversed(temp)))
Output:
'1 234 567 8912'
Using list comprehensions we can do this in a single very confusing line as
num = 12345678912.34
''.join(list(reversed(list(''.join([c+' ' if(ix%3 == 0 and ix!=0) else c for ix, c in enumerate(reversed(str(round(num))))])))))
'1 234 567 8912'
Another approch is to use locale if available on your system of course, and use format.
import locale
for v in ('fr_FR.UTF-8', 'en_GB.UTF-8'):
locale.setlocale(locale.LC_NUMERIC, v)
print(v, '>> {:n}'.format(111222333999))
May as well share another slightly different variant, but still can't shake the feeling that there's some sublime way that we just can't see. Haven't marked any answers as correct yet, because i'm convinced python can do this in a simpler way, somehow. What's also driving me crazy is that if i remember correctly VB's format command can handle this (with a pattern like "### ####0"). Maybe it's just a case of not understanding how to use Python's .format correctly.
The below accepts a float or decimal and a list indicating split positions. If there are still digits in the string after consuming the last split position, it re-applies that until it reaches the start of the string.
def format_number(num, pat, sep=' '):
fmt = []
strn = "{:.0f}".format(num)
while strn:
p = pat.pop() if pat else p
fmt.append(strn[-p:])
strn = strn[:-p] if len(strn) > p else ''
return sep.join(fmt[::-1])
>>> format_number(123456789, [3, 4])
>>> '12 345 6789'
>>> format_number(1234567890, [3])
>>> '1 234 567 890'

Compare numbers in form: 12,3K , 1,84M in python

In need to compare numbers which look like: 12,3K , 1,84M, etc
eg:
a = 12,3K
b = 1,84M
if b > a :
print b
You need to use replace for it:
a = ("12,3K", "1,84M")
numbers = {"K": 1000, "M": 1000000}
result = []
for value in a:
if value:
i = value[-1]
value = float(value[:-1].replace(',', '.')) * numbers[i]
result.append(int(value))
print max(result)
You can add more numbers to dictionary and you will get more results.
I would recommend a function to convert a and b into the corresponding number like so (also I'd make a and b strings:
def convert(num):
return num.replace(',','').replace('K','000').replace('M','000000')
a = '12,3K'
b = '1,84M'
if convert(b) > convert(a) :
print b
If your values are strings, then the re module would make it easy to replace commas with '' and K or M with 3 or 6 zeroes. Then wrap in int() and compare. Where / how are you getting the values you're comparing?

using an integer in a string to create a dictionary (or list) with that many numbers

so i have this text (wordnet) file made up of numbers and words, for example like this -
"09807754 18 n 03 aristocrat 0 blue_blood 0 patrician"
and i want to read in the first number as a dictionary name (or list) for the words that follow. the layout of this never changes, it is always an 8 digit key followed by a two digit number, a single letter and a two digit number. This last two digit number (03) tells how many words (three words in this case) are associated with the first 8 digit key.
my idea was that i would search for the 14th place in the string and use that number to run a loop to pick in all of the words associated with that key
so i think it would go something like this
with open('nouns.txt','r') as f:
for line in f:
words = range(14,15)
numOfWords = int(words)
while i =< numOfWords
#here is where the problem arises,
#i want to search for words after the spaces 3 (numOfWords) times
#and put them into a dictionary(or list) associated with the key
range(0,7) = {word(i+1), word(i+2)}
Technically i am looking for whichever one of these makes more sense:
09807754 = { 'word1':aristocrat, 'word2':blue_blood , 'word3':patrician }
or
09807754 = ['aristocrat', 'blue_blood', 'patrician']
Obviously this doesnt run but if anyone could give me any pointers it would be greatly appreciated
>>> L = "09807754 18 n 03 aristocrat 0 blue_blood 0 patrician".split()
>>> L[0], L[4::2]
('09807754', ['aristocrat', 'blue_blood', 'patrician'])
>>> D = {}
>>> D.update({L[0]: L[4::2]})
>>> D
{'09807754': ['aristocrat', 'blue_blood', 'patrician']}
For the extra line in your comment, some extra logic is needed
>>> L = "09827177 18 n 03 aristocrat 0 blue_blood 0 patrician 0 013 # 09646208 n 0000".split()
>>> D.update({L[0]: L[4:4 + 2 * int(L[3]):2]})
>>> D
{'09807754': ['aristocrat', 'blue_blood', 'patrician'], '09827177': ['aristocrat', 'blue_blood', 'patrician']}
res = {}
with open('nouns.txt','r') as f:
for line in f:
splited = line.split()
res[splited[0]] = [w for w in splited[4:] if not w.isdigit()]
Output:
{'09807754': ['aristocrat', 'blue_blood', 'patrician']}

Categories

Resources