need help on the highlighted lines in the python code:
n = int(input())
student_marks = {}
for _ in range(n):
name, *line = input().split() <--- doubt
scores = list(map(float, line)) <--- doubt
student_marks[name] = scores
print (student_marks)
The output which i get is below:
2
abc 23 34 45
def 45 46 47
{'abc': [23.0, 34.0, 45.0], 'def': [45.0, 46.0, 47.0]}
Can you guys please help me explain the need for the marked line in the code. Couldn't quite get the concept.
name, *line = input().split() <--- doubt
input() # reads single line of input
# 'abc 23 34 45'
.split() # splits it into a list of whitespace separated tokens
# ['abc', '23', '34', '45']
name, *line = ... # name is assigned first token, line a list of the remaining tokens
name # 'abc'
line # ['23', '34', '45']
scores = list(map(float, line)) # maps float function onto the list of strings
scores # [23.0, 34.0, 45.0]
Some references:
map
str.split
input
starred assignment
1)name, *line = input().split() <--- doubt
The * is being used to store the additional returns from the split statement.
Let's say you have:
name, *line = input().split()
print(name)
print(*line)
And you ran this code and say you entered: "abc 23 34 45", it will print out:
abc
[23, 34, 45]
2)scores = list(map(float, line)) <--- doubt
Here, the map() function returns a map object(which is an iterator) of the results after applying the given function to each item of a given iterable (list, tuple, etc.).
For more understanding, refer: https://www.geeksforgeeks.org/python-map-function/
->map() function maps float function onto the list of strings.
For example:
line = [23, 34, 45]
then scores = list(map(float, line)) will output to: scores = [23.0, 34.0, 45.0]
The line name, *line = input().split() splits the input by white spaces, assigning the first item into name, and the rest of the items are assigned to line as a list, which, in the next line scores = list(map(float, line)), gets mapped to a list of floating numbers into scores.
name, *line = "foo 23 34 45".split()
assert(name == "foo");
assert(line == ["23", "34", "45"])
https://docs.python.org/3/tutorial/controlflow.html#arbitrary-argument-lists
scores = list(map(float, line))
assert(scores == [23.0, 34.0, 45.0])
https://docs.python.org/3/library/functions.html
you want to get data form user we use
scanf('%d %d', %name, %value)
name, value=input(), input()
Another solution is that:
name, value=input().split()
use split method
Related
I am writing a program that can take in three numbers and three letters on seperate lines. The program will then seperate the numbers into items of a list and will do the same for the letters in a separate list. The program will then sort the the numbers from lowest to highest. I then want to assign the numbers to letters (In a sorted letter order (I.E. A=5, B=16, C=20) and then print the letters in the order it came in from the input (I.E. Input: CAB, output: 20 5 16). I have been able to sort the variables and can do all of this with if statements and for loops but I feel like there is a prettier and more efficient way of doing this. I want to be able to take the input letter string that's divided by use of a list and format the string to insert the variables in the correct order. I know that the globals() and locals() functions do something similar to this but can not figure out how to use them. Any ideas?
Working code:
nput_numbers_list = ((input()).split(" "))
input_letters = (input())
input_letters_list = []
for i in range(3):
input_letters_list.append(input_letters[i])
input_numbers_list = [int(x) for x in input_numbers_list]
input_numbers_list.sort()
print_string = ""
for i in range(3):
if input_letters[i] == "A":
print_string = print_string + A + " "
if input_letters[i] == "B":
print_string = print_string + B + " "
if input_letters[i] == "C":
print_string = print_string + C + " "
print(print_string)
My (wanted) code:
input_numbers_list = ((input()).split(" "))
input_letters = (input())
input_letters_list = []
for i in range(3):
input_letters_list.append(input_letters[i])
input_numbers_list = [int(x) for x in input_numbers_list]
input_numbers_list.sort()
A = str(input_numbers_list[0])
B = str(input_numbers_list[1])
C = str(input_numbers_list[2])
final_list = ["""Magic that turns input_letters_list into variables in the order used by list and then uses that order"""]
print("{} {} {}".format("""Magic that turns final_list into variables in the order used by list and then puts it in string""")
Wanted/expected input and output:
Input: "5 20 16"
Input: "CAB"
Output: "20 5 16"
As others have suggested, you will likely want an answer that uses a dictionary to lookup numbers given letters.
##----------------------
## hardcode your input() for testing
##----------------------
#input_numbers = input()
#input_letters = input()
input_numbers = "5 20 16"
input_letters = "CAB"
input_numbers_list = input_numbers.split(" ")
input_letters_list = list(input_letters) # not technically needed
##----------------------
##----------------------
## A dictionary comprehension
# used to construct a lookup of character to number
##----------------------
lookup = {
letter: number
for letter, number
in zip(
sorted(input_letters_list),
sorted(input_numbers_list, key=int)
)
}
##----------------------
##----------------------
## use our original letter order and the lookup to produce numbers
##----------------------
result = " ".join(lookup[a] for a in input_letters_list)
##----------------------
print(result)
This will give you your requested output of:
20 5 16
There is a lot going on with the construction of the dictionary lookup, so let's unpack it a bit.
First of, it is based on calling zip(). This function takes two "lists" and pairs their elements up creating a new "list". I use "list" in quotes as it is more like iterables and generators. Anyways. let's take a closer look at:
list(zip(["a","b","c"], ["x","y","z"]))
this is going to give us:
[
('a', 'x'),
('b', 'y'),
('c', 'z')
]
So this is how we are going to pairwise combine our numbers and letters together.
But before we do that, it is important to make sure that we are going to pair up the "largest" letters with the "largest" numbers. To ensure that we will get a sorted version of our two lists:
list(
zip(
sorted(input_letters_list), #ordered by alphabet
sorted(input_numbers_list, key=int) #ordered numerically
)
)
gives us:
[
('A', '5'),
('B', '16'),
('C', '20')
]
Now we can feed that into our dictionary comprehension (https://docs.python.org/3/tutorial/datastructures.html).
This will construct a dictionary with keys of our letters in the above zip() and values of our numbers.
lookup = {
letter: number
for letter, number
in zip(
sorted(input_letters_list),
sorted(input_numbers_list, key=int)
)
}
print(lookup)
Will give us our lookup dictionary:
{
'A': '5',
'B': '16',
'C': '20'
}
Note that our zip() technically gives us back a list of tuples and we could also use dict() to cast them to our lookup.
lookup = dict(zip(
sorted(input_letters_list),
sorted(input_numbers_list, key=int)
))
print(lookup)
also gives us:
{
'A': '5',
'B': '16',
'C': '20'
}
But I'm not convinced that clarifies what is going on or not. It is the same result though so if you feel that is clearer go for it.
Now all we need to do is go back to our original input and take the letters one by one and feed them into our lookup to get back numbers.
Hope that helps.
Its very weird the case when you need to conver string to a variable, when you feel that you need something like that a dictionary will probably do the trick.
in this case the solution can be done with the following code.
input_numbers_list = (("5 20 16").split(" "))
input_letters = ("CAB")
input_letters_list = [letter for letter in input_letters]
input_numbers_list = [int(x) for x in input_numbers_list]
rules = {}
for letter, value in zip(input_letters_list, input_numbers_list):
rules[value] = letter
output = ""
input_numbers_list.sort()
for numb in input_numbers_list:
output += rules[numb] + " "
print(output)
And you can use it for n inputs and outputs.
The idea of a dictionary is that you have keys, and values, so for a key (in this case text of letters) you can get a value, similar to a variable. Plus is super fast.
You could use a dictionary for that! https://www.w3schools.com/python/python_dictionaries.asp
EDIT: the output is more consistent with the requested one, but it should be "20 16 5" instead of "20 5 16" if I understood your problem well.
input_numbers_list = input().split(" ")
input_letters = input()
# Create new dictionary
input_dict = {}
# Fill it by "merging" both lists
for index, letter in enumerate(input_letters):
input_dict[letter] = input_numbers_list[index]
# Sort it by converting it into a list and riconverting to dict
sorted_dict = {k: v for k, v in sorted(list(input_dict.items()))}
# Print the result
output = ''
for value in sorted_dict.values():
output += value + ' '
print(output)
Using zip function helps
num_arr = list(map(int,input().split(' ')))
word = input()
num_arr.sort()
word = sorted(word)
mapper = dict(zip(word,num_arr))
result = ' '.join(map(str,[mapper[i] for i in word]))
print(result)
I have a list of sentence and I want to convert it into a diction only include the username and the age.
list=['#David, the age is 27', '#John, the age is 99', '#rain, the age is 45']
The output I want to get is a dictionary like
dic={David:27,John:99,rain:45}
Thanks for the help
You can define a custom function, apply it to each string via map, then feed to dict:
L = ['#David, the age is 27', '#John, the age is 99', '#rain, the age is 45']
def key_value_extractor(x):
x_split = x.split(',') # split by ','
name = x_split[0][1:] # take 1st split and exclude first character
age = int(x_split[1].rsplit(maxsplit=1)[-1]) # take 2nd, right-split, convert to int
return name, age
res = dict(map(key_value_extractor, L))
{'David': 27, 'John': 99, 'rain': 45}
Try a dict comprehension:
dic = {x.split()[0].strip(',#'): int(x.split()[-1]) for x in member_list}
If you need clarification on the parts of the expression, please tell.
EDIT: Clarification, as required:
Ok, so:
enclosing the expression in {} tells it we are making a dictionary with this comprehension. x represents each member string within this comprehension
x.split() splits the string into a list of substrings, on "space" sign (by default, can be adjusted)
with [0] we grab the first substring ["#David,"]
with .strip(',#') we remove the comma and # character around the name
with this we have created the dictionary key
Key value: int(x.split()[-1])
x.split()[-1] takes the last substring ('27')
enclosing it in int() we turn it into an integer
You can use dictionary comprehension
l = ['#David, the age is 27', '#John, the age is 99', '#rain, the age is 45']
X = {item.split(',')[0][1:]:int(item.split(',')[1].rsplit(maxsplit=1)[-1]) for item in l}
print(X)
#output
{'David': 27, 'John': 99, 'rain': 45}
I am really struggling with making a python code. Any help would be very much appreciated. The function I need to write a code for is below. Since the numbers are strings in the input, I know I can't somehow separate by name of the student, I think I must somehow convert the numbers into int/float and then somehow separate the list into sublists by name (ie. by string) but I don't know how to accomplish this. I know I can use map(int, ) to turn something into int but it doesn't seem to be working and the number of grades (ie. str i need to turn into float) can be different with any input
Thanks!
Code:
def string_list(L):
'''(list of str) -> list of list
Given a list of strings where each string has the format:
'name, grade, grade, grade, ...' return a new list of
lists where each inner list has the format :
[name (str), grade, grade, grade, ...] where the name
is a string and the grades are floats.
>>> string_list(['Joe, 60, 90, 80', 'Harry, 60, 70', 'Jill, 98.5, 100, 95.5, 98'])
[['Joe', 60.0, 90.0, 80.0], ['Harry', 60.0, 70.0], ['Jill', 98.5, 100.0, 95.5, 98.0]]
'''
def string_list(L):
final_list = []
for element in L:
new_entry = element.split(',') # Split on commas; returns a list of strings
new_entry = [x.strip() for x in new_entry] # Remove whitespace from each string in list
new_entry[1:] = [float(x) for x in new_entry[1:]] # Cast all entries but the first to float
final_list.append(new_entry)
return final_list
Solution
Got to love the magic oneliner list comprehension!
[[float(val) if val.strip().isdigit() else val.strip() for val in person.split(',')] for person in L]
The same list comprehension but for narrow screens:
[[float(val) if val.strip().isdigit() else val.strip()
for val in person.split(',')]
for person in L ]
Usage
Which you could slap into your function like so:
def string_list(L):
return [[float(val) if val.strip().isdigit() else val.strip() for val in person.split(',')] for person in L]
And use it like so:
>>> L = ["Joe, 60, 90, 80", "Harry, 60, 70", "Jill, 98.5, 100, 95.5, 98"]
>>> string_list(L)
[['Joe', 60.0, 90.0, 80.0],
['Harry', 60.0, 70.0],
['Jill', '98.5', 100.0, '95.5', 98.0]]
Breakdown
List comprehensions are awesome but ugly! So let's decompose this behemoth into its corresponding parts:
for person in L]
For each item (e.g. "Joe, 60, 90, 80") in our list
for val in person.split(',')
If we split each of those strings into a list of strings such that
"Joe, 60, 90, 80"-> ["Joe","60","90","80"] and store iterate over each of those elements ("Joe" or "60" and so on) storing each of those values as val
float(val) if val.strip().isdigit() else val.strip()
If val only consists of digit characters (.isdigit()), then convert it to a float. Otherwise, return the string (without white-space characters like space via .strip())
[[<code> for val in person.<more>] for person in L]
The inner brackets group the elements of the person, without them you only get a single list of strings.
If you wanted a single list you would need to reorder the for <thing> in <list>'s like so:
[float(val) if val.strip().isdigit() else val.strip()
for person in L
for val in person.split(',') ]
I have a textfile and it looks like this :
zor:10
zor:21
bob:30
qwerty:46
I want it to look like {'zor': [10, 21,], 'bob': [30]} etc but the numbers keep getting replaced when I add multiple scores to a name I split the scores so that the names and scores are in separate positions.
elif schClass == '2':
schClass = open("scores2.txt", 'r')
li = open("scores2.txt", 'r')
data = li.read().splitlines()
for li in data:
name = li.split(":")[0]
score = li.split(":")[1]
if name not in diction1:
diction1[name] = score
elif name in diction1 :
diction1[name] = diction1[name + int(score)]
print(diction1)
You are not building lists; simply use the dict.setdefault() method to insert a list object when the key is missing, and append your values:
diction1 = {}
with open("scores2.txt", 'r') as infile:
for line in infile:
name, _, score = line.partition(':')
diction1.setdefault(name, []).append(int(score))
I took the liberty to clean up your code a little; I'm using the file as a context manager so that it is closed again automatically. By looping directly over the file you get individual lines, no need to split first. And I used str.partition() to split just the once (it is more efficient for that case than str.split() is).
Demo:
>>> from io import StringIO
>>> sample = '''\
... zor:10
... zor:21
... bob:30
... qwerty:46
... '''
>>> diction1 = {}
>>> with StringIO(sample) as infile:
... for line in infile:
... name, _, score = line.partition(':')
... diction1.setdefault(name, []).append(int(score))
...
>>> diction1
{'bob': [30], 'qwerty': [46], 'zor': [10, 21]}
I'm facing problem with this. I have 10,000 rows in my dictionary and this is one of the rows
Example: A (8) C (4) G (48419) T (2) when printed out
I'd like to get 'G' as an answer, since it has the highest value.
I'm currently using Python 2.4 and I have no idea how to solve this as I'm quite new in Python.
Thanks a lot for any help given :)
Here's a solution that
uses a regexp to scan all occurrences of an uppercase letter followed by a number in brackets
transforms the string pairs from the regexp with a generator expression into (value,key) tuples
returns the key from the tuple that has the highest value
I also added a main function so that the script can be used as a command line tool to read all lines from one file and the write the key with the highest value for each line to an output file. The program uses iterators, so that it is memory efficient no matter how large the input file is.
import re
KEYVAL = re.compile(r"([A-Z])\s*\((\d+)\)")
def max_item(row):
return max((int(v),k) for k,v in KEYVAL.findall(row))[1]
def max_item_lines(fh):
for row in fh:
yield "%s\n" % max_item(row)
def process_file(infilename, outfilename):
infile = open(infilename)
max_items = max_item_lines(infile)
outfile = open(outfilename, "w")
outfile.writelines(max_items)
outfile.close()
if __name__ == '__main__':
import sys
infilename, outfilename = sys.argv[1:]
process_file(infilename, outfilename)
For a single row, you can call:
>>> max_item("A (8) C (4) G (48419) T (2)")
'G'
And to process a complete file:
>>> process_file("inputfile.txt", "outputfile.txt")
If you want an actual Python list of every row's maximum value, then you can use:
>>> map(max_item, open("inputfile.txt"))
max(d.itervalues())
This will be much faster than say d.values() as it is using an iterable.
Try the following:
st = "A (8) C (4) G (48419) T (2)" # your start string
a=st.split(")")
b=[x.replace("(","").strip() for x in a if x!=""]
c=[x.split(" ") for x in b]
d=[(int(x[1]),x[0]) for x in c]
max(d) # this is your result.
Use regular expressions to split the line. Then for all the matched groups, you have to convert the matched strings to numbers, get the maximum, and figure out the corresponding letter.
import re
r = re.compile('A \((\d+)\) C \((\d+)\) G \((\d+)\) T \((\d+)\)')
for line in my_file:
m = r.match(line)
if not m:
continue # or complain about invalid line
value, n = max((int(value), n) for (n, value) in enumerate(m.groups()))
print "ACGT"[n], value
row = "A (8) C (4) G (48419) T (2)"
lst = row.replace("(",'').replace(")",'').split() # ['A', '8', 'C', '4', 'G', '48419', 'T', '2']
dd = dict(zip(lst[0::2],map(int,lst[1::2]))) # {'A': 8, 'C': 4, 'T': 2, 'G': 48419}
max(map(lambda k:[dd[k],k], dd))[1] # 'G'