Python 2.7 reduce lambda statement conversion to list comprehension - python

I was examining a code written in python but I got confused with the following line.
return ( reduce(lambda x, y: x + y[0],myList, 0)/len(Actions), )
This code takes x and y as an input sums x and y's first element. After that I think it reduces myList to the value of x+y[0] . How can I accomplish this with using list comprehension instead of using lambda.

The part that corresponds well to a list comprehension is what the reducing function does with its second argument y:
tmp = [ y[0] for y in myList ]
The reducing function then combines this list one element at a time with the "accumulator" x:
x = 0 # The third argument to reduce
tmp = [ y[0] for y in myList ]
for y in tmp:
x += y
or more simply
x = 0
for y in myList:
x += y[0]
or, as you have probably recognized by now
sum(y[0] for y in myList)

Related

Finding Minimum of Long List Python

I am working with numbers in a list separated by commas. I am trying to find the minimum number in this data for multiple ranges.(i.e. Find the minimum number listed in the range 0-100)
My problem is whenever I run the following code, I get a long list of about 4 repeating integers. Any ideas on how to get just one number?
Thank you!
mylist = []
def sort_data(x, y):
for line in filename:
for number in line.split():
if int(number) > x and int(number) < y:
mylist.append(int(number))
print(min(mylist))
This is what you can use:
from itertools import ifilter # only needed in Python 2
def sort_data(x, y):
if x > y: x, y = y, x # x should be less than or equal to y
Min = None
for line in File:
_Min = min(ifilter(lambda num: x < num < y, map(int, line.split(","))))
Min = min(_Min, Min) if Min is not None else _Min
return Min
ifilter is just an iterator version of filter(function, iterable), which constructs a sequence of elements from iterable for which function returns True
map(function, iterable) applies function to each element of iterable
Please note that if your data is comma-separated, you should use line.split(",").
Also, if you're running Python 3.x, you should use simply filter as it already returns an iterator, unlike the Python 2 version. This code is based on iterators, which allow you to work with large streams of data without copying them into memory, which makes this function very memory and speed efficient.
You can try this:
x = 3
y = 95
l = [1, 3, 100, 340, 678, 89, 123, 67]
new_l = [i for i in l if i in range(x, y)]
Output:
[3, 89, 67]
Minor edits to your code should work
mylist = []
def sort_data(x, y):
for line in filename:
for number in line.split(','):#added comma
if int(number) > x and int(number) < y:
mylist.append(int(number))
print(min(mylist)) #changed tab level

How can I fix this algorithm?

I am trying to create a function in Python. This function should be able to create a list of whole numbers less than or equal to the number provided. I've created an empty list, a variable called y and a while loop. In this while loop, as long as y <= x, the results of the subsequent equations are appended to the empty list, and y increments by 1. However, when I call this function, I get a list with only one element. How can I fix this?
def fff(x):
numbers = []
y = 2
while(y <= x):
x = x - (x - y)
numbers.append(x)
y += 1
return numbers
>>> fff(10)
[2]
That function already exists, more or less.
Python 2
def fff(x):
return range(1,x+1)
Python 3
def fff(x):
return list(range(1,x+1))
If you look at this line x = x - (x - y) and think of your inputs, you will see the problem. if x initially equals 10, then x - (x - y) equals 2, and y will equal 3, therefore breaking out of your loop.
If you are trying to mimic the range function then this is how you would do it:
def fff(x):
numbers = []
y = 1
while(y <= x):
numbers.append(y)
y += 1
return numbers

Confused as to these loops are equal

Confused as to why one for loop works but one doesn't? Aren't they doing the same thing? Like shouldn't x = y?
x = 3
for i in range(8):
if i > x:
print i, ">", x
i = x
print x
y = 3
for i in range(8):
if y < i:
print y, "<", i
y = i
print y
Both are not same in first you have assignment (every time 3 to i) i = x, while in second you assign counter's i value to y as y = i.
shouldn't x = y?
No, after first loop x remains 3 whereas after second loop y becomes 7.
No.
In the first loop you are not reassigning the value of x. So x is unchanged in the loop.
In the second loop, you are updating y every time y is less than i

List comprehension for loops Python

I use a lot of N dimensional arrays and it gets a pain to have to write such indented code and I know some codes can be replaced with list comprehensions and inline statements. For example:
for x in (0,1,2,3):
for y in (0,1,2,3):
if x < y:
print (x, y, x*y)
can be replaced with:
print [(x, y, x * y) for x in (0,1,2,3) for y in (0,1,2,3) if x < y]
But how could I change the action instead of print to do something else like:
total = x+y
So what I want to do is something like:
[(total+=x+y) for x in (0,1,2,3) for y in (0,1,2,3) if x < y]
However this doesn't work
Is there a smart way to do this rather than:
for x in (0,1,2,3):
for y in (0,1,2,3):
if x < y:
total+=x+y
sum works here:
total = sum(x+y for x in (0,1,2,3) for y in (0,1,2,3) if x < y)
As an alternative to writing loops N levels deep, you could use itertools.product():
In [1]: import itertools as it
In [2]: for x, y in it.product((0,1,2,3),(0,1,2,3)):
...: if x < y:
...: print x, y, x*y
0 1 0
0 2 0
0 3 0
1 2 2
1 3 3
2 3 6
This extends naturally to N dimensions.
Use numpy. This lets you use arrays that add up like vectors:
x = numpy.arange(3)
y = numpy.arange(3)
total = x + y
With the modified question, add a call to sum as well
total = numpy.sum(x+y)
Reduce function directly reduces collective items to single item. You can read more about them here, but this should work for you:
total=reduce(lambda x,y:x+y,range(4))
or
total=reduce(lambda x,y:x+y,(0,1,2,3))
Another possibility is:
for x,y in ((x,y) for x in (0,1,2,3) for y in (0,1,2,3) if x < y):
print (x, y, x * y)
In this way you can iterate over anything you'd use in a list comprehension without actually creating the comprehended list (if you get my meaning ;) If comprehended list is big, maybe so big it saturates or even doesn't fit in memory, that's quite handy..

Python: for statement behavior

My question concerns the output of this statement:
for x in range(4), y in range(4):
print x
print y
Results in:
[0, 1, 2, 3]
2
True
2
It seems there is a comparison involved, I just can't figure out why the output is structured like this.
My guess is that you're running this from an interactive console, and already had y defined with a value of 2 (otherwise, you'd get NameError: name 'y' is not defined). That would lead to the output you observed.
This is due to for x in range(4), y in range(4): actually being equivalent to the following when evaluated:
for x in (range(4), y in range(4)):
which reduces to...
for x in ([0,1,2,3], 2 in range(4)):
which again reduces to...
for x in ([0,1,2,3], True):
This then results in 2 iterations of the for loop, since it iterates over each element of the tuple:
x = [0,1,2,3]
x = True.
(And of course, y is still 2.)
You've created a weird, weird thing there.
>>> y = 2
>>> range(4), y in range(4)
([0, 1, 2, 3], True)
The y in range(4) is a membership test.
The range(4), y in range(4) is a pair of items; a tuple.
The variable x is set to range(4), then the result of y in range(4).
The variable y is just laying around with a value; it is not set by the for statement.
This only works hacking around on the command line typing random stuff with y left laying around.
This isn't sensible Python code at all.
[And yes, the word in has two meanings. So do ()'s and several other pieces of syntax.]
You seem to have y defined prior to running this code. What you're iterating over is a two-item tuple: first item is range-generated list, second is True, which is result of the y in range(4):
>>> y = 2
>>> for x in range(4), y in range(4):
print x, 'x'
print y, 'y'
[0, 1, 2, 3] x
2 y
True x
2 y
What I suspect you were trying to do is to iterate over two variables from two lists. Use zip for this.
Dav nailed down perfectly why the syntax you wrote doesn't work.
Here are the syntaxes that do work for what you're probably trying to do:
If you want all 4 x 4 combinations for x and y, you want 2 nested loops:
for x in range(4):
for y in range(4):
print x, y
Or if you really want to use one loop:
import itertools
for (x, y) in itertools.product(range(4), range(4)):
print x, y
itertools.product() generates all possible combinations:
This is less readable than 2 loops in this simple case, but the itertools module has many other powerful functions and is worth knowing...
If you want x and y to advance in parallel over two sequences (aka "lock-step" iteration):
for (x, y) in zip(range(4), range(4)):
print x, y
# `zip(range(4), range(4))` is silly since you get x == y;
# would be useful for different sequences, e.g.
# zip(range(4), 'abcd')
[Background: The name zip comes from Haskell; think about how a Zipper takes one tooth from here and one from there:
zip() cuts off to the length of the shortest sequence; the itertools module has other variants...]

Categories

Resources