two loops together in python - python

File
sims 10 500
dettol 45 200
nims 200 540
Code:
for E, w in vb, T.readline():
name, qty, price = w.split()
print("you bought" + str(vb[E]) + "from" + name)
Description
I want to run two loop together, one for a file and one for an array. Also, the expected output for each iteration would be
>>> "you bought 1 from nims"
if "nims" has 1 quantity.
I used like to do
for i, k in j, T.readline:
but it's not working.

You haven't clarified what vb is, but I don't think that loop is doing what you think it does. First, here's what it looks like to the interpreter:
for E, w in (vb, T.readline()):
This isn't going to take each element of vb and each line of T. Instead, it's going to take vb and attempt to unpack it to E and w, and then do the same thing for T.readline() on the second iteration. For example:
>>> a = (1, 2)
>>> b = (5, 6)
>>> for i, j in a, b: print(i, j)
1 2
3 4
Notice that it doesn't print the 0th element of a and b, but both elements of a followed by both elements of b. If you wanted to combine them you would use zip:
>>> for i, j in zip(a, b): print(i, j)
1 3
2 4
Finally, T.readline() the way you are using it is not going to give you each line of T. Rather, it's going to take the first line in T (assuming you don't read other lines prior to the loop) and iterate over the characters of that line.

You are probably looking for zip:
with open("test") as T:
vb = [1, 2, 3]
for E, w in zip(vb, T):
name, qty, price = w.split()
print("you bought {} from {}".format(E, name))
Also note that there were two other errors in your code:
you want to iterate all the lines in the file T, not the letters in the first T.readline()
E is already the element from the list, not the index of that element
Note that in Python 2.x, zip will consume the entire file at once, so it that file is very large, you probably want to use itertools.izip instead, which creates an iterator. In Python 3.x, zip itself is an iterator.

In addition to paidhima's asnwer, you could maybe consider using enumerate() such as
for i,line in enumerate(T):
print i, line
assuming that T is the name of your file. This would print
0 sims 10 500
1 dettol 45 200
2 nims 200 540
Is this what you want?

Related

How to do print in python in specific way

l = ['a1',1,'b1',2,'c1',3]
how to print like below(expected out)
a1 1
b1 2
c1 3
Do I need to do zip function for this? or any other way
Slice with a stride of 2 and zip with an offset slice:
l = ['a1',1,'b1',2,'c1',3]
for a, b in zip(l[::2], l[1::2]):
print(a, b)
A for loop would do the trick (as mentioned in other answers)
But a list comprehension will also work:
[print(str(x[0]) + ' ' + str(x[1])) for x in zip(l[0::2], l[1::2])]
How does this work?
l[0::2] takes every element from l, starting at index 0, until the last element, and with steps of 2 (in other words it takes all the even elements)
l[1::2] takes all the odd elements
zip bundles those into a zip object (iterable tuples) of pairs
the last step is iterating over those and executing the print function for each of them
A for loop will solve the problem:
l = ['a1',1,'b1',2,'c1',3]
for index in range(0, len(l), 2):
print(l[index] + " " + str(l[index+1]))
It starts at index 0 (at "a1") and goes in steps of 2 (jumping to "b1"). The print statement adds an offset of 1 to access the value in between.
Alternatives for the print statement itself, not changing the structure of the code:
print(l[index], str(l[index+1]), sep=" ") # use space as a separator
print(f"{l[index]} {str(l[index+1])}") # use f-string for formatting
For this i would recommend using dictionaries if its possible, i don't know what you are trying to do.
Use them like this:
l = {'a1':1,'b1':2,'c1':3}
for key, value in l.items():
print("{} {}".format(key, value))

Input in a cycle (Python)

I'm learning Python as my first language and now I trying to resolve this problem:
I have to make a loop where I ask the user which elements from a list they want to remove and then remove the elements selected. The loop stops only when the user insert a specific number that corresponds to the length of the list increased by 1 (so I won't have any problem).
I have another problem related to this:
elements_list = ['a','b','c','d']
length_list = len(elements_list)
for i in range(0, length_list):
print (str(i) + str(')') + elements_list[i])
This will print the list starting with 0:
0) a
1) b
2) c
3) d
What do I have to do if I want the list start with 1? (if I use 1 instead of 0 in the range it doesn't print the first element of the list)
In Python, lists can be iterated directly, and enumerate is used to generate indexes. Its optional second parameter gives a starting number:
>>> elements = ['a','b','c','d']
>>> for i,v in enumerate(elements,1):
... print('{}) {}'.format(i,v))
...
1) a
2) b
3) c
4) d
If using Python 3.6+, formatting output is even more simple using f-strings:
>>> elements = ['a','b','c','d']
>>> for i,v in enumerate(elements,1):
... print(f'{i}) {v}')
...
1) a
2) b
3) c
4) d
Refs:
enumerate
str.format
Formatted string literals
One way would be to add a 1 in the range, then subtract a 1 from the index
elements_list=['a','b','c','d']
lenght_list=len(elements_list)
for i in range(1, lenght_list+1):
print (str(i) + str(')') + elements_list[i-1])
Edit: TheoretiCAL's approach is even more straight forward, simply adding 1 to the print statement achieves the same thing.

Compare two lists for same entries at same place

I am trying to compare two lists for the same element at the same index. The idea is to verify whether both lists contain same element at the same index. If yes, I want to count such occurrences. Here is my code:
count = 0
a = ['.ps2\n >|<4 *|*.ps2xml', '.c\n >|<2 *|*.wsc', '.h\n >|<2 *|*.wsh', '.c\n >|<2 *|*.chm', '.h\n >|<2 *|*.hta' ]
b = ['.ps2xml', '.chm', '.hta']
for x in a:
for y in b:
if y==x[x.index(" *|*")+4:]:
print "match"
count += 1
print count
This gives me a count of 3. What I expect is 1 because only first element of b matched with a's first element. The second element of both lists differ. The third elements are also different. The remaining elements in list a should not count as there is no such index in b.
Hope it makes sense. Thanks
In that case, you should not use nested loops (since this means you will repeat the search over b for each line in a); but use a zip(..):
for x,y in zip(a,b):
if y==x[x.index(" *|*")+4:]:
print "match"
count += 1
print count
zip takes some iterators and generates tuples. In this case the i-th tuple is thus (a[i],b[i]) so to speak.
Short solution using min() function(to get a limit size of compared sequences):
for i in range(min([len(a), len(b)])):
if (a[i][a[i].index('*|*') + 3:] == b[i]):
count += 1
print(count)
The output:
1
does the match have to be qualified as following '*|*' ?
if not then really simple is:
sum([1 for e, f in zip(a, b) if f in e])
or in later versions of python where iterator args are automatically unpacked:
sum(f in e for e, f in zip(a, b)) # relies on bools True, False = ints 1, 0
if the match is just the last bit you could split
'.ps2\n >|<4 *|*.ps2xml'.split(" *|*")
Out[13]: ['.ps2\n >|<4', '.ps2xml']
'.ps2\n >|<4 *|*.ps2xml'.split(" *|*")[1]
Out[14]: '.ps2xml'
sum([1 for e, f in zip(a, b) if f in e.split(" *|*")[1]])
and while sum() is more "intentional" len() could be used for a speed advantage since it doesn't have to iterate over the list

How to check if sum of 3 integers in list matches another integer? (python)

Here's my issue:
I have a large integer (anywhere between 0 and 2^32-1). Let's call this number X.
I also have a list of integers, unsorted currently. They are all unique numbers, greater than 0 and less than X. Assume that there is a large amount of items in this list, let's say over 100,000 items.
I need to find up to 3 numbers in this list (let's call them A, B and C) that add up to X.
A, B and C all need to be inside of the list, and they can be repeated (for example, if X is 4, I can have A=1, B=1 and C=2 even though 1 would only appear once in the list).
There can be multiple solutions for A, B and C but I just need to find one possible solution for each the quickest way possible.
I've tried creating a for loop structure like this:
For A in itemlist:
For B in itemlist:
For C in itemlist:
if A + B + C == X:
exit("Done")
But since my list of integers contains over 100,000 items, this uses too much memory and would take far too long.
Is there any way to find a solution for A, B and C without using an insane amount of memory or taking an insane amount of time? Thanks in advance.
you can reduce the running time from n^3 to n^2 by using set something like that
s = set(itemlist)
for A in itemlist:
for B in itemlist:
if X-(A+B) in s:
print A,B,X-(A+B)
break
you can also sort the list and use binary search if you want to save memory
import itertools
nums = collections.Counter(itemlist)
target = t # the target sum
for i in range(len(itemlist)):
if itemlist[i] > target: continue
for j in range(i+1, len(itemlist)):
if itemlist[i]+itemlist[j] > target: continue
if target - (itemlist[i]+itemlist[j]) in nums - collections.Counter([itemlist[i], itemlist[j]]):
print("Found", itemlist[i], itemlist[j], target - (itemlist[i]+itemlist[j]))
Borrowing from #inspectorG4dget's code, this has two modifications:
If C < B then we can short-circuit the loop.
Use bisect_left() instead of collections.Counter().
This seems to run more quickly.
from random import randint
from bisect import bisect_left
X = randint(0, 2**32 - 1)
itemset = set(randint(0,X) for _ in range(100000))
itemlist = sorted(list(itemset)) # sort the list for binary search
l = len(itemlist)
for i,A in enumerate(itemlist):
for j in range(i+1, l): # use numbers above A
B = itemlist[j]
C = X - A - B # calculate C
if C <= B: continue
# see https://docs.python.org/2/library/bisect.html#searching-sorted-lists
i = bisect_left(itemlist, C)
if i != l and itemlist[i] == C:
print("Found", A, B, C)
To reduce the number of comparisons, we enforce A < B < C.

multiplying in a list python

I am doing some homework and I am stuck. I supposed to write a code in Python 3, that reads a text file that is like a bill with an amount of numbers. I am supposed to write the code so it will calculate the total amount.
I figured that a bill(simple example) will contain a number and the a prise. like:
2 10$
1 10 $
and so on
So I figured that I create a list with all numbers in it and then I want to multiply the first with the second element in the list and then jump in the list so the tird and the fourth element get multiply and so on, until there is no more numbers in my list. During this happens I want the sums of every multiplication in a new list called sums there they later will be summed.
my code looks like this so far:
file = open('bill.txt')
s = file.read()
file.close()
numbers = []
garbage = []
for x in s.split():
try:
numbers.append(float(x))
except ValueEror:
garbage.append()
print(numbers)
for n in numbers:
sums = []
start = 0
nxt = start + 1
t = numbers[start]*numbers[nxt]
if n <= len(numbers):
start += 2
nxt += 2
summor.append(t)
if n == len(numbers):
print(sum(sums))
The problem in your code is likely that you keep resetting sums for every number in the list. So you basically keep forgetting the sums you previously collected. The same applies to start and nxt. If you move these definition outside of the loop, and also fix the summor.append(t) to sums.append(t) it should almost work. Also note that the loop variable n does not iterate over indexes of numbers but over the actual items (i.e. the numbers). So the check at the end n == len(numbers) is unlikely to do what you expect. Instead, you can just put the print after the loop because you know that when you reached that point the loop is over and all numbers have been looked at.
A common idiom is to use zip to combine two elements with each other. Usually, you use zip on two different iterators or sequences, but you can also use zip on the same iterator for a single list:
>>> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> it = iter(numbers)
>>> for a, b in zip(it, it):
print(a, b)
1 2
3 4
5 6
7 8
As you can see, this will group the numbers automatically while iterating through the list. So now you just need to collect those sums:
>>> sums = []
>>> it = iter(numbers)
>>> for a, b in zip(it, it):
sums.append(a * b)
>>> sum(sums)
100
And finally, you can shorten that a bit more using generator expressions:
>>> it = iter(numbers)
>>> sum(a * b for a, b in zip(it, it))
100
This may be a typo when you entered it but on your 2nd line of data there is a space between the amount and $ and no space on the line above. This will cause some problems when striping out the $.
Try this:
total = 0
with open('data.txt', 'r') as f:
lines = f.readlines()
amounts = []
garbage = []
for line in lines:
try:
multiples = line.split()
multiplier = multiples[0]
amount = multiples[1].strip('$\n')
amounts.append(int(multiplier)*float(amount))
except:
garbage.append(line)
total = sum(amounts)
print(total)
With some minor formatting on output or the text data you should be able to get the result you want. Here is the txt data I used:
2 10$
1 10$
3 20.00$
and the output is:
90.0
Also, you may want to get away from file = open('data.txt', 'r') which requires you to explicitly close your file. Use with open('data.txt', 'r') as f: and your file will implicitly be closed.
Firstly, I would say, quite a good attempt. If you don't want to be spoiled, you should not read the code I have written unless you try out the corrections/improvements yourself. (I am not a pro)
Well, like you said every line contains 2 numbers that need be multiplied, you should start by reading line by line & not individual numbers as that might get troublesome.
file = open('bill.txt')
s = file.readlines()
file.close()
numbers = []
garbage = []
for line in s:
try:
line.strip('$') # removes the trailing $ sign for easy number extraction
numbers.append(map(int, line.split()))
except ValueEror:
garbage.append(line)
print(numbers)
Later, when summing up the multiplication of the number & the bills, you probably won't require a list for that, instead a sum integer variable should be enough.
sum = 0
for num, bill in numbers:
sum += num * bill
print("The total amount is", sum)
Several things:
sums = [] is inside the loop for n in numbers. This means you're resetting the sums list every time. You should move this outside the loop.
The same applies to start = 0 and nxt = start + 1. These values now keep being reset to 0 and 1 respectively for each number in the list.
You are comparing if n <= len(numbers): but what is n? It's an actual value in your list of numbers, it doesn't represent the position in the list. You should replace this with while start < len(numbers): - as long as the starting position is still within the list we should keep going. This also means you can remove n from your code.
The code now becomes:
sums = []
start = 0
nxt = start + 1
while start < len(numbers):
t = numbers[start]*numbers[nxt]
start += 2
nxt += 2
sums.append(t)
print(sum(sums))

Categories

Resources