Python - reduce ,two dimensional array - python

I 'm trying to use reduce on two-dimensional array which consists of coordinates.I don't have a lot of experience with reduce .I have a function called func and I have to apply this function to each element of the array. For example:
func=lambda x:x-1
array=[[5,9],[10,3]]
reduce (lambda x,y: ...,array)
OUTPUT should be -> [[4,8],[9,2]]
I just decrement each element by 1 . Thanks.

reduce takes a function of two arguments and applies it cumulatively to the elements of a sequence - but all you want to do is subtract one from every element of every sublist, so I'm not sure why you would want to use reduce here.
I suggest this list comprehension:
>>> lst = [[5,9],[10,3]]
>>> [[x-1 for x in sub] for sub in lst]
[[4, 8], [9, 2]]
Or if you want to use your lambda function:
>>> [map(lambda x: x-1, sub) for sub in lst]
[[4, 8], [9, 2]]
I find the first one to be more readable, though.

you don't need to use reduce to decrease each element's value.
Try using map
arr = map( lambda x:[x[0]-1,x[1]-1],arr)

Related

Maximum sum of sub list in a list of lists

Making my first steps in Python.
I have a list of lists and i'm trying to return the sub list with largest sum of all sub lists.
For now I just have the max sum itself.
Ex: this code returns 18, but I need to return [3,3,3,3,3,3]
Any directions?
Thanks
def find_biggest(lst):
inner_list_sum = []
for i in range(len(lst)):
inner_list_sum.append(sum(lst[i])) # list of elements sums
return max(inner_list_sum) # I actually need the element itself...not the max sum
print(find_biggest([[1,2,3,4], [1,2,3,3], [1,1], [3,3,3,3,3,3]]))
Use max with key=sum
Ex:
data = [[1,2,3,4], [1,2,3,3], [1,1], [3,3,3,3,3,3]]
print(max(data, key=sum))
Output:
[3, 3, 3, 3, 3, 3]
OK
Since I'm not allowed to use (max(data, key=sum)).
I did this not very elegant code, but it was accepted a correct answer
def find_biggest(lst):
inner_list_sum = []
for i in range(len(lst)):
inner_list_sum.append(sum(lst[i])) # list of elements sums
max_element=max(inner_list_sum)
seq_index= inner_lis
import functools
def find_biggest(lst):
return functools.reduce(lambda x, y : x if sum(x) > sum(y) else y, lst)
Here, the used lambda expression is the function equivalent to find the greatest sum and lst is iterable.
Please note: reduce will directly work for python2, you need to import functools
for python3only.
Using functools.reduce

How to get the first element of a complex list in Python

In Python, I used to get first element of a 2-d list by
a = [[0, 1], [2, 3]]
a[:][0]
# [0, 2]
Now, the list is sort of complex, the way to get the first elements does not work
a = [['sad', 1], ['dsads', 2]]
a[:][0]
# ['sad', 1]
I do not know what is the difference here. And how to get the first elements in this simple way, rather than
[e[0] for e in a]
you could use in-built zip :
aggregates elements from each of the iterables
a = [['sad', 1], ['dsads', 2]]
zip(*a)[0]
#results :
('sad', 'dsads')
You can convert the final result to list from tuple if necessary.
* is used to flatten the list into its elements - zip accepts iterables as positional arguments. zip is sort of matrix transposition.
As commented, your first solution (a[:][0]) is not correct, it simply takes the first element of the list. Here you need to first transform the list such that each first elements are grouped into separate list, and so on for second, third .. elements. Then take the first element.
Update:
From #Rawing's comment:
If the list is very large, consider using
next(itertools.izip(*a))
This is the iterator version - this takes the list element only as necessary. In this case, it constructs each elment of the result one at a time, since we need the first element, we use next a single time to get the next (thus, first here) element of the iterator.
Using numpy :
>>> a = [['sad', 1], ['dsads', 2]]
>>> import numpy
>>> my_array = numpy.array(a)
>>> print my_array[:,0]
['sad' 'dsads']

Sorting based on one of the list among Nested list in python

I have a list as [[4,5,6],[2,3,1]]. Now I want to sort the list based on list[1] i.e. output should be [[6,4,5],[1,2,3]]. So basically I am sorting 2,3,1 and maintaining the order of list[0].
While searching I got a function which sorts based on first element of every list but not for this. Also I do not want to recreate list as [[4,2],[5,3],[6,1]] and then use the function.
Since [4, 5, 6] and [2, 3, 1] serves two different purposes I will make a function taking two arguments: the list to be reordered, and the list whose sorting will decide the order. I'll only return the reordered list.
This answer has timings of three different solutions for creating a permutation list for a sort. Using the fastest option gives this solution:
def pyargsort(seq):
return sorted(range(len(seq)), key=seq.__getitem__)
def using_pyargsort(a, b):
"Reorder the list a the same way as list b would be reordered by a normal sort"
return [a[i] for i in pyargsort(b)]
print using_pyargsort([4, 5, 6], [2, 3, 1]) # [6, 4, 5]
The pyargsort method is inspired by the numpy argsort method, which does the same thing much faster. Numpy also has advanced indexing operations whereby an array can be used as an index, making possible very quick reordering of an array.
So if your need for speed is great, one would assume that this numpy solution would be faster:
import numpy as np
def using_numpy(a, b):
"Reorder the list a the same way as list b would be reordered by a normal sort"
return np.array(a)[np.argsort(b)].tolist()
print using_numpy([4, 5, 6], [2, 3, 1]) # [6, 4, 5]
However, for short lists (length < 1000), this solution is in fact slower than the first. This is because we're first converting the a and b lists to array and then converting the result back to list before returning. If we instead assume you're using numpy arrays throughout your application so that we do not need to convert back and forth, we get this solution:
def all_numpy(a, b):
"Reorder array a the same way as array b would be reordered by a normal sort"
return a[np.argsort(b)]
print all_numpy(np.array([4, 5, 6]), np.array([2, 3, 1])) # array([6, 4, 5])
The all_numpy function executes up to 10 times faster than the using_pyargsort function.
The following logaritmic graph compares these three solutions with the two alternative solutions from the other answers. The arguments are two randomly shuffled ranges of equal length, and the functions all receive identically ordered lists. I'm timing only the time the function takes to execute. For illustrative purposes I've added in an extra graph line for each numpy solution where the 60 ms overhead for loading numpy is added to the time.
As we can see, the all-numpy solution beats the others by an order of magnitude. Converting from python list and back slows the using_numpy solution down considerably in comparison, but it still beats pure python for large lists.
For a list length of about 1'000'000, using_pyargsort takes 2.0 seconds, using_nympy + overhead is only 1.3 seconds, while all_numpy + overhead is 0.3 seconds.
The sorting you describe is not very easy to accomplish. The only way that I can think of to do it is to use zip to create the list you say you don't want to create:
lst = [[4,5,6],[2,3,1]]
# key = operator.itemgetter(1) works too, and may be slightly faster ...
transpose_sort = sorted(zip(*lst),key = lambda x: x[1])
lst = zip(*transpose_sort)
Is there a reason for this constraint?
(Also note that you could do this all in one line if you really want to:
lst = zip(*sorted(zip(*lst),key = lambda x: x[1]))
This also results in a list of tuples. If you really want a list of lists, you can map the result:
lst = map(list, lst)
Or a list comprehension would work as well:
lst = [ list(x) for x in lst ]
If the second list doesn't contain duplicates, you could just do this:
l = [[4,5,6],[2,3,1]] #the list
l1 = l[1][:] #a copy of the to-be-sorted sublist
l[1].sort() #sort the sublist
l[0] = [l[0][l1.index(x)] for x in l[1]] #order the first sublist accordingly
(As this saves the sublist l[1] it might be a bad idea if your input list is huge)
How about this one:
a = [[4,5,6],[2,3,1]]
[a[0][i] for i in sorted(range(len(a[1])), key=lambda x: a[1][x])]
It uses the principal way numpy does it without having to use numpy and without the zip stuff.
Neither using numpy nor the zipping around seems to be the cheapest way for giant structures. Unfortunately the .sort() method is built into the list type and uses hard-wired access to the elements in the list (overriding __getitem__() or similar does not have any effect here).
So you can implement your own sort() which sorts two or more lists according to the values in one; this is basically what numpy does.
Or you can create a list of values to sort, sort that, and recreate the sorted original list out of it.

Built in way to apply a function to successive members of a list and return a new list

I'm looking for a built in function in python that applies a function to each element and the next element within a list (or other iterable), returning the set of results in a new list. I don't know if one is built in or not, but I'm attempting to approach this in a functional way if possible.
Example:
l = [1,2,3,4,5]
# returns [3,5,7,9]
# add(1,2) add(2,3) add(3,4) add(4,5)
My actual use case is that I have a list of vectors of the form numpy.array([1,2,3]), and I want to find the difference between each successive vector.
Actual example:
l = [numpy.array([1,2,3]), numpy.array([2,7,6]), numpy.array([4,5,6])]
# find the difference between each vector (l[0]-l[1], l[1]-[l2], .. etc)
You want pairwise() and map().
The most straightforward way to do this would be in a list comprehension:
a = [l[i] + l[i+1] for i in range(len(l)-1)]
Alternatively, you could use a little builtin magic:
map(sum, zip(l, l[1:]))
Finding the differences between successive entries of a NumPy array can be done with numpy.diff():
>>> a = numpy.array([5, 2, 3, 1, 4])
>>> numpy.diff(a)
array([-3, 1, -2, 3])
This will be much faster than any pure-Python solution.
Edit: Here's an example for a 2d array:
>>> a = numpy.array([[1,2,3], [2,7,6], [4,5,6]])
>>> numpy.diff(a, axis=0)
array([[ 1, 5, 3],
[ 2, -2, 0]], dtype=int32)

Using python to return a list of squared integers

I'm looking to write a function that takes the integers within a list, such as [1, 2, 3], and returns a new list with the squared integers; [1, 4, 9]
How would I go about this?
PS - just before I was about to hit submit I noticed Chapter 14 of O'Reilly's 'Learning Python' seems to provide the explanation I'm looking for (Pg. 358, 4th Edition)
But I'm still curious to see what other solutions are possible
You can (and should) use list comprehension:
squared = [x**2 for x in lst]
map makes one function call per element and while lambda expressions are quite handy, using map + lambda is mostly slower than list comprehension.
Python Patterns - An Optimization Anecdote is worth a read.
Besides lambda and list comprehensions, you can also use generators. List comprehension calculates all the squares when it's called, generators calculate each square as you iterate through the list. Generators are better when input size is large or when you're only using some initial part of the results.
def generate_squares(a):
for x in a:
yield x**2
# this is equivalent to above
b = (x**2 for x in a)
squared = lambda li: map(lambda x: x*x, li)
You should know about map built-in which takes a function as the first argument and an iterable as the second and returns a list consisting of items acted upon by the function.
For e.g.
>>> def sqr(x):
... return x*x
...
>>> map(sqr,range(1,10))
[1, 4, 9, 16, 25, 36, 49, 64, 81]
>>>
There is a better way of writing the sqr function above, namely using the nameless lambda having quirky syntax. (Beginners get confused looking for return stmt)
>>> map(lambda x: x*x,range(1,10))
[1, 4, 9, 16, 25, 36, 49, 64, 81]
Apart from that you can use list comprehension too.
result = [x*x for x in range(1,10)]
a = [1, 2, 3]
b = [x ** 2 for x in a]
good remark of kefeizhou, but then there is no need of a generator function, a generator expression is right:
for sq in (x*x for x in li):
# do
You can use lambda with map to get this.
lst=(3,8,6)
sqrs=map(lambda x:x**2,lst)
print sqrs

Categories

Resources