Taking single value input in Python - python

I was attempting to do one kata problem in Python, where I have two lists of input, let's say weight and value, which was getting input in the order (value1, weight1, value2, weight2,....)
If it were C++, I could just take one element at a time with cin to my arrays. But with Python I don't know how to take this input.
If the input is like
60 10 100 20 120 30 (in a single line)
I want my two lists val and w have values
val=[60,100,120]
w=[10,20,30]
How to take this kind of inputs in Python? Is it possible to read only one input at a time, like cin does in C++?

You can read space-separated input to a list using splitand then use slicing to get the odd/even indexed elements:
val = input().split()
val = [int(i) for i in val] #to integer
w = val[1::2] # get only odd indices
val = val[0::2] # get only even indices
print(val) # [60,100,120]
print(w) # [10,20,30]
You can then use regular indexing to get individual elements in the lists.

This should do it.
values = input("Enter values: ").split(" ")
if(len(values) % 2 != 0):
print("Error, uneven number of values and weights")
else:
val = []
w = []
for i in range(0, len(values) - 1, 2):
val.append(values[i])
w.append(values[i+1])
print("val: ", val)
print("w: ", w)

No you cannot as far as I know. input() is a function that reads one line at a time as an entire string.
A popular way to make a list out of an entire line of space separated integers is using the in-built map() function and split() method of a string object:
numbers = map(int, input.split())
numbers will now contain the list of numbers on that line.
Firstly, input() reads the entire line as a string including spaces.
split() function splits the input at space, you can also pass in a string argument to make it split anywhere you want, i.e a custom delimiter like , and creates a list of strings of those numbers
map() calls int() on each of the numbers in that list.
In C++, just like you need to know the size of input in advance, you can run a for loop on the list to now split values and weights into two lists.
val, w = [], []
for i in range(len(numbers)):
if i % 2 == 0: val.append(numbers[i])
else: w.append(numbers[i])
For better performance(relevant for large input size), you can even skip the map() step, and do something like this:
numbers = input().split()
val, w = [], []
for i in range(len(numbers)):
if i % 2 == 0: val.append(int(numbers[i]))
else: w.append(int(numbers[i]))

Here's a simple solution:
a = "60 10 100 20 120 30"
split_a = a.split(" ")
val = [e for (i, e) in enumerate(split_a) if i % 2 == 0]
w = [e for (i, e) in enumerate(split_a) if i % 2 == 1]
# or shorter with slicing (start:stop:step)
val = [e for e in split_a[0::2]]
w = [e for e in split_a[1::2]]

I am not sure what cin does but I assume the input you have is a string. One way you could do is to split it into a list of ints. And then create your val and w lists and append your values into the lists. (The first, third, fifth, etc would be your val list)
my_input_list = my_input.split(' ')
Read more here.

Related

Python code to count integers based on length and starting digit

I have a list of numbers of varying lengths stored in a file, like this...
98
132145
132324848
4435012341
1254545221
2314565447
I need a function that looks through the list and counts every number that is 10 digits in length and begins with the number 1. I have stored the list in both a .txt and a .csv with no luck. I think a big part of the problem is that the numbers are integers, not strings.
`import regex
with open(r"C:\Desktop\file.csv") as file:
data = file.read()
x = regex.findall('\d+', data)
def filterNumberOne(n):
if(len(n)==10:
for i in n:
if(i.startswith(1)):
return True
else:
return False
one = list(filter(filterNumberOne, x))
print(len(one))`
You could simply do like this :
# Get your file content as a string.
with open(r"C:\Desktop\file.csv") as f:
s = " ".join([l.rstrip("\n").strip() for l in f])
# Look for the 10 digits number starting with a one.
nb = [n for n in s.split(' ') if len(n)==10 and n[0]=='1']
In your case, the output will be:
['1254545221']
So I ended up using the following, seems to work great..
def filterNumberOne(n):
if (len(n)==10:
if str(n)[0] == '1':
return True
else:
return False
one = list(filter(filterNumberOne, x ))
print(len(one))

The count() method counts wrong

Here is my task to solve.
For a list of integers, find and print the items that appear in the list
only once. Items must be printed in the order in which they are
are in the incoming list.
I wrote the code but it also counts two and three digit numbers as a single digits. What's the problem?
x = []
a = input()
a.split(" ")
for i in a:
if a.count(i) == 1:
x.append(i)
print(x)
User Mechanical Pig provides the answer, split does not work in-place, since you're discarding its result what you're looking at is the count of each character in the string, not each space-separated sub-string.
The standard library also contains a collection which is ready-made for this use-case: collections.Counter. You can just give it a sequence of items and it'll collate the counts, which you can then filter:
print([k for k, v in collections.Counter(a.split()).items() if v == 1])
a.split(" ") does not change the value of a, so it is still a string and not a list. Hence when you iterate over a, you only get single characters.
str.split is a method that returns a list, but does not magically turn the string into a list. So you need to assign the value it returns to a variable (for example, to a, if you don't want to hold on to the input string).
You can assign the variable as mentioned above or you can directly use the split function in the loop.
x = []
a = input()
for i in a.split(" "):
if a.count(i) == 1:
x.append(i)
print(x)
or split when you are reading the input.
x = []
a = input().split(" ")
for i in a:
if a.count(i) == 1:
x.append(i)
print(x)
Using the Counter class from the collections module is the right way to do this but here's another way without any imports where you effectively have your own limited implementation of a Counter:
a = '1 2 3 4 4 5 6 7 7 7'
d = {}
for n in a.split():
d[n] = d.get(n, 0) + 1
for k, v in d.items():
if v == 1:
print(k)
Output:
1
2
3
5
6

Reading an array from stdin using input() function throws an EOF error

Basically, I wish to sum the elements of the array provided in stdin. Why is it saying that list index is out of range? Is there anything special about the python input() function?
length = int(input())
li = []
for i in range(0, length):
li[i] = int(input())
sum = 0
for item in li:
sum = sum + item
Input
first line : length of array
second line : elements of the array.
EDIT : second line is a single string, not space separated integers.
3
1 2 3
Output:
Traceback (most recent call last):
File "./prog.py", line 6, in <module>
IndexError: list assignment index out of range
your question pretty much got answered, I just wanna show you a couple of tricks to make your program more simple and pythonic.
Instead of the for-loop try:
li = [int(i) for i in input().split(" ")]
And instead of the way you're calculating sum, try:
sum(li)
or even better:
sumOfItems = sum(int(i) for i in input().split(" "))
The thing with python lists is that you cannot assign a particular value to a position when that position originally does not exist, that is, the length of the list is less than the position that you want to change.
What you are trying to do is assign the value to a particular position in the list (called index) but since the list is empty, it's length is 0 and hence the index is out of range( that is it is not available for modifiying. That is why python is raising Index out of range error.
What you can try is:
l=[]
length=int(input())
for i in length:
l.append(int(input())
sum=0
for num in l:
sum=sum+num
You can solve this in a single line without even taking in the length. But you have to enter space separated values in a single line:
s = 0
for item in list(map(int, input ().split())):
s += item
If you want to input one integer per line, then you'll need the length(or a sentinel value):
s = 0
len = int(input())
li = [int(input ()) for _ in range(len)]
for item in li:
s = s + item
The second line of input turned out to be a single string and not space separated integers.
So I had to split the string, then convert the strings to integers to calculate their sum. Some of the methods mentioned above didn't work.
The list comprehension method will work in the space separated case, and is perfectly fine.
length = int(input())
l = input().split() # List of strings of integers.
S = 0
for item in l:
S += int(item) # Converting string to int
print(S)
You can't assign values to locations of a list that doesn't exist
try this:
length = int(input())
li = list(range(length))
for i in range(0, length):
li[i] = int(input())
sum = 0
for item in li:
sum = sum + item
you can also do something like this:
length = int(input())
li = []
for i in range(0, length):
li.append(int(input()))
total = sum(li)
print(total)

Eliminate numbers between 1 and 100 present in list

I have written a code that should input numbers from the user and report back the numbers from 1 to 100 that are missing from their input.
My code is below which doesn't work:
num_list = []
number = input('Enter numbers (remember a space): ')
number.split()
num_list.append(number)
for i in range(1, 101):
if i in num_list:
continue
else:
print(i, end =', ')
The code outputs all the numbers from 1 to 100 but doesn't exclude the numbers.
Note: The code has to exclude all the numbers entered not only one number.
E.g. if the user inputted 1 2 3 4 the output should start from 5 and list the numbers through to 100.
There are three of problems
1) your are not saving the returned list from split method
result = number.split()
2) Use extend instead of append
num_list.extend(result)
3) By default input will read everything as string, you need to convert them into int from string after splitting, below is example using List Comprehensions
result = [int(x) for x in number.split()]
append : Will just add an item to the end of the list
So in you case after appending user input your list will be
num_list.append(number) #[[1,2,3,4,5]] so use extend
extend : Extend the list by appending all the items from the iterable.
num_list.append(number) #[1,2,3,4,5]
Note : If the num_list empty you can directly use result from split method, no need of extend

list index out of range in simple Python script

I just started learning Python and want to create a simple script that will read integer numbers from user input and print their sum.
The code that I wrote is
inflow = list(map(int, input().split(" ")))
result = 1
for i in inflow:
result += inflow[i]
print(result)
It gives me an error
IndexError: list index out of range
pointing to result += inflow[i] line. Can't see what am I doing wrong?
BTW, is there more elegant way to split input flow to the list of integers?
You can also avoid the loop altogether:
inflow = '1 2 34 5'
Then
sum(map(int, inflow.split()))
will give the expected value
42
EDIT:
As you initialize your result with 1 and not 0, you can then also simply do:
sum(map(int, input.split()), 1)
My answer assumes that the input is always valid. If you want to catch invalid inputs, check Anton vBR's answer.
Considering: I just started learning Python
I'd suggest something like this, which handle input errors:
inflow = raw_input("Type numbers (e.g. '1 3 5') ") #in py3 input()
#inflow = '1 2 34 5'
try:
nums = map(int, inflow.split())
result = sum(nums)
print(result)
except ValueError:
print("Not a valid input")
for i in list gives the values of the list, not the index.
inflow = list(map(int, input().split(" ")))
result = 1
for i in inflow:
result += i
print(result)
If you wanted the index and not the value:
inflow = list(map(int, input().split(" ")))
result = 1
for i in range(len(inflow)):
result += inflow[i]
print(result)
And finally, if you wanted both:
for index, value in enumerate(inflow):
script that will read integer numbers from user input and print their
sum.
try this :
inflow = list(map(int, input().split(" ")))
result = 0
for i in inflow:
result += i
print(result)
If you were going to index the list object you would do:
for i in range(len(inflow)):
result += inflow[i]
However, you are already mapping int and turning the map object into a list so thus you can just iterate over it and add up its elements:
for i in inflow:
result += i
As to your second question, since you arent doing any type testing upon cast (i.e. what happens if a user supplies 3.14159; in that case int() on a str that represents a float throws a ValueError), you can wrap it all up like so:
inflow = [int(x) for x in input().split(' ')] # input() returns `str` so just cast `int`
result = 1
for i in inflow:
result += i
print(result)
To be safe and ensure inputs are valid, I'd add a function to test type casting before building the list with the aforementioned list comprehension:
def typ(x):
try:
int(x)
return True # cast worked
except ValueError:
return False # invalid cast
inflow = [x for x in input().split(' ') in typ(x)]
result = 1
for i in inflow:
result += i
print(result)
So if a user supplies '1 2 3 4.5 5 6.3 7', inflow = [1, 2, 3, 5, 7].
What your code is doing, in chronological order, is this:
Gather user input, split per space and convert to integer, and lastly store in inflow
Initialize result to 1
Iterate over every item in inflow and set item to i
Add the current item, i to result and continue
After loop is done, print the result total.
The broken logic would be at step 4.
To answer your question, the problem is that you're not gathering the index from the list as expected-- you're iterating over each value in the list opposed to the index, so it's really undefined behavior based on what the user inputs. Though of course, it isn't what you want.
What you'd want to do is:
inflow = list(map(int, input().split(" ")))
result = 1
for i in range(len(inflow)):
result += inflow[i]
print(result)
And on your last regard; there are two real ways to do it, one being the way you're doing right now using list, map and:
inflow = [int(v) for v in input().split()]
IMO the latter looks better. Also a suggestion; you could call stdlib function sum(<iterable>) over a list of integers or floats and it'll add each number and return the summation, which would appear more clean over a for loop.
Note: if you're splitting per whitespace you can just call the str.split() function without any parameters, as it'll split at every whitespace regardless.
>>> "hello world!".split()
['hello', 'world!']
Note: also if you want extra verification you could add a bit more logic to the list comprehension:
inflow = [int(v) for v in input().split() if v.isdigit()]
Which checks whether the user inputted valid data, and if not, skip past the data and check the following.

Categories

Resources