String-formatting two zipped NumPy arrays in Python 3 - python

I would like to use pythons format function to print subsequent numbers of a numpy array.
I have got two numpy arrays, let's say:
x=[1 2 3 4]
y=[5 6 7 8]
Now I would like to print this:
1 5 2 6 3 7 4 8
I can almost achieve this by:
print('{} {} {} {}'.format(*zip(x,y)))
but it yields:
(1,5) (2,6) (3,7) (4,8)
Of course I could use
"{} {} {} {}".format(x[0], y[0], x[1], y[1])
and so on but this requires to know the length of the array.
Note:
This line of code does what I want
print(*["%f %f"%(a,b) for a,b in zip(x,y)])
but this does use the old formatting style and I would like to know if it's possible with the new one, too. It also looks a little bit funky, I think :-D

Do the following:
x=[1, 2, 3, 4]
y=[5, 6, 7, 8]
result = ' '.join([str(i) for e in zip(x, y) for i in e])
print(result)
Output
1 5 2 6 3 7 4 8

You can use itertools.chain to interleave the elements from both lists:
list(chain.from_iterable(zip(x, y)))
[1, 5, 2, 6, 3, 7, 4, 8]
And if you want to print all elements joined as you specify you can do:
print(*chain.from_iterable(zip(x, y)))
1 5 2 6 3 7 4 8

what about some numpy
np.array(list(zip(a,b))).flatten()
output
array([1, 5, 2, 6, 3, 7, 4, 8])

You can use zip() to iterate through two iterables at the same time.
l1 = [0, 2, 4, 6, 8]
l2 = [1, 3, 5, 7, 9]
for i, j in zip(l1, l2):
print(i)
print(j)
Output:
0
1
2
3
4
5
6
7
8
9

Since you use numpy, what about
>>> ' '.join(np.vstack((x, y)).T.flatten().astype(str))
'1 5 2 6 3 7 4 8'

It's also possible with itertools.starmap:
>>> print(*starmap("{} {}".format, zip(x, y)))
1 5 2 6 3 7 4 8
Normally, the method given by #yatu with itertools.chain is the way to go, especially if you want all elements to be separated by spaces. But starmap could come handy when you'd want to have some special formatting between the pairs, for example:
>>> print(*starmap("{}:{}".format, zip(x, y)))
1:5 2:6 3:7 4:8

Throwing another into the mix
("{} "*len(x)*2).format(*np.ravel(list(zip(x,y))))
'1 5 2 6 3 7 4 8 '

Related

Sorting matrix columns

I have a matrix 4*5 and I need to sort it by several columns.
Given these inputs:
sort_columns = [3, 1, 2, 4, 5, 2]
matrix = [[3, 1, 8, 1, 9],
[3, 7, 8, 2, 9],
[2, 7, 7, 1, 2],
[2, 1, 7, 1, 9]]
the matrix should first be sorted by the 3nd column (so the values 8, 8, 7, 7), then the sorted result should again be sorted by column 1 (values 3, 3, 2, 2) and so on.
So, after first sorting by column 3, the matrix would be:
2 7 7 1 2
2 1 7 1 9
3 1 8 1 9
3 7 8 2 9
and sorting on column 1 then has no effect as the values are already in the right order. The next column, 2, then makes the order:
2 1 7 1 9
3 1 8 1 9
2 7 7 1 2
3 7 8 2 9
etc.
After sorting on all the sort_columns numbers, I expect to get the result:
2 7 7 1 2
3 1 8 1 9
2 1 7 1 9
3 7 8 2 9
This is my code to sort the matrix:
def sort_matrix_columns(matrix, n, sort_columns):
for col in sort_columns:
column = col - 1
for i in range(n):
for j in range(i + 1, n):
if matrix[i][column] > matrix[j][column]:
temp = matrix[i]
matrix[i] = matrix[j]
matrix[j] = temp
which is called like this:
sort_matrix_columns(matrix, len(matrix), sort_columns)
But when I do I get the following wrong result:
3 1 8 1 9
2 1 7 1 9
2 7 7 1 2
3 7 8 2 9
Why am I getting the wrong order here? Where is my sort implementation failing?
The short answer is that your sort implementation is not stable.
A sort algorithm is stable when two entries in the sorted sequence keep the same (relative) order when their sort key is the same. For example, when sorting only by the first letter, a stable algorithm will always sort the sequence ['foo', 'flub', 'bar'] to be ['bar', 'foo', 'flub'], keeping the 'foo' and 'flub' values in the same relative order. Your algorithm would swap 'foo' and 'bar' (as 'f' > 'b' is true) without touching 'flub', and so you'd end up with ['bar', 'flub', 'foo'].
You need a stable sort algorithm when applying sort multiple times as you do when using multiple columns, because subsequent sortings should leave the original order applied by preceding sort operations when the value in the current column is the same between two rows.
You can see this when your implementation sorts by column 5, after first sorting on columns 3, 1, 2, 4. After those first 4 sort operations the matrix looks like this:
2 1 7 1 9
3 1 8 1 9
2 7 7 1 2
3 7 8 2 9
Your implementation then sorts by column 5, so by 9, 9, 2, 9. The first row is then swapped with the 3rd row (2 1 7 1 9 and 2 7 7 1 2, leaving the other rows all untouched. This changed the relative order of all the columns with a 9:
2 7 7 1 2 < - was third
3 1 8 1 9 < - so this row is now re-ordered!
2 1 7 1 9 < - was first
3 7 8 2 9
Sorting the above output by the 2nd column (7, 1, 1, 7) then leads to the wrong output you see.
A stable sort algorithm would have moved the 2 7 7 1 2 row to be the first row without reordering the other rows:
2 7 7 1 2 < - was third
2 1 7 1 9 < - was first
3 1 8 1 9 < - was second, stays *after* the first row
3 7 8 2 9 < - was third, stays *after* the second row
and sorting by the second column produces the correct output.
The default Python sort implementation, TimSort (named after its inventor, Tim Peters), is a stable sort function. You could just use that (via the list.sort() method and a sort key function):
def sort_matrix_columns(matrix, sort_columns):
for col in sort_columns:
matrix.sort(key=lambda row: row[col - 1])
Heads-up: I removed the n parameter from the function, for simplicity's sake.
Demo:
>>> def pm(m): print(*(' '.join(map(str, r)) for r in m), sep="\n")
...
>>> def sort_matrix_columns(matrix, sort_columns):
... for col in sort_columns:
... matrix.sort(key=lambda row: row[col - 1])
...
>>> sort_columns = [3, 1, 2, 4, 5, 2]
>>> matrix = [[3, 1, 8, 1, 9],
... [3, 7, 8, 2, 9],
... [2, 7, 7, 1, 2],
... [2, 1, 7, 1, 9]]
>>> sort_matrix_columns(matrix, sort_columns)
>>> pm(matrix)
2 1 7 1 9
3 1 8 1 9
2 7 7 1 2
3 7 8 2 9
You don't need to use loop, if you reverse the sort_columns list and use that to create a single sort key, you can do this with a single call:
def sort_matrix_columns(matrix, sort_columns):
matrix.sort(key=lambda r: [r[c - 1] for c in sort_columns[::-1]])
This works the same way, the most significant sort is the last column, only when two rows have the same value (a tie) would the one-but-last column sort matter, etc.
There are other stable sort algorithms, e.g. insertion or bubble sort would work just as well here. Wikipedia has a handy table of comparison sort algorithms that includes a 'stable' column, if you wanted to implement sorting yourself still.
E.g. here is a version using insertion sort:
def insertionsort_matrix_columns(matrix, sort_columns):
for col in sort_columns:
column = col - 1
for i in range(1, len(matrix)):
for j in range(i, 0, -1):
if matrix[j - 1][column] <= matrix[j][column]:
break
matrix[j - 1], matrix[j] = matrix[j], matrix[j - 1]
I didn't use a temp variable to swap two rows. In Python, you can swap two values simply by using tuple assignments.
Because insertion sort is stable, this produces the expected outcome:
>>> matrix = [[3, 1, 8, 1, 9],
... [3, 7, 8, 2, 9],
... [2, 7, 7, 1, 2],
... [2, 1, 7, 1, 9]]
>>> insertionsort_matrix_columns(matrix, sort_columns)
>>> pm(matrix)
2 1 7 1 9
3 1 8 1 9
2 7 7 1 2
3 7 8 2 9

Generating all sums of one element per line in a matrix in Python

Let us say I have a matrix of 4 lines by 3 columns. E.g.:
1 2 3
4 5 6
7 8 9
10 11 12
I would like to generate the list of all possible sums, a sum being computed by taking only 1 element per line, for each line. E.g.:
1 + 4 + 7 + 10 = 22
3 + 5 + 7 + 11 = 26
...
How could I do this in Python?
Perform a Cartesion product, summing the values in each result of that product. You can use itertools, as it provides an iterator over a Cartesion product:
import itertools
m=[[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9],
[10, 11, 12]]
res = map(sum, itertools.product(*m))
print(list(res))

Python create a sequence of non repeating numbers

I want to create a sequence something like this [[1,2],[3,4],[5,6],..].
Here is what I tried and got:
n = 3 # I need three lists
for i in range(0,n+1,1):
print(i+1,i+2)
1 2
2 3
3 4
4 5
Expected output:
1 2
3 4
5 6
n = 3
pairs = [list([i, i + 1]) for i in range (1, 2 * n, 2)]
for pair in pairs:
for x in pair:
print(x, end = ' ')
print()
This prints:
1 2
3 4
5 6
And the list pairs so formed is:
[[1, 2], [3, 4], [5, 6]]
Take step of 2 and end at n*2
n=3
output = []
for i in range(0,n*2,2):
print(i+1,i+2)
output.append([i+1,i+2])
print(output)
1 2
3 4
5 6
[[1, 2], [3, 4], [5, 6]]
After a trial, I found the following answer:
for i in range(0,n,1):
print(2*i+1,2*i+2)

Rearranging numbers from list in python3

Lets say I have an list of numbers
a = [ 1,2,3,4,5,6,7,8,9,10]
and I want to print the output as
1
2 3
4 5 6
7 8 9 10
How can I do it in python3.
My attempt:
a = [1,2,3,4,5,6,7,8,9,10]
for i in a:
print(a[i]," ")
i=i+1
I'm getting IndexError: list index out of range and also I don't know to print 1 element in 1'st row , 2nd and 3rd in second row and so on.
One way to do this in Python 3 is to use islice on an iterator :
from itertools import islice
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
it = iter(a)
print('\n'.join([' '.join([str(u)for u in islice(it, i)])for i in range(1,5)]))
output
1
2 3
4 5 6
7 8 9 10

Make lists with out commas in python

I want to make a list of list without comma.
data=[[2,124,123],[3,4,5]]
for i in data:
print(x[0],x[1],x[2])
gives
2 124 123
3 4 5
How do I write the code so that it gives me:
[ 2 124 123 ]
[ 3 4 5 ]
for any kind of input with out using built in functions. The number of paddings for all elements is equal to the length of the largest element in the the list.
Thank you in advance.
Just unpack the arguments to print, eg:
data=[[2,124,123],[3,4,5], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]
for i in data:
print(*i)
Gives:
2 124 123
3 4 5
1 2 3 4 5 6 7 8 9 10
If you only wanted the first n many then slice it, then unpack it, eg:
for i in data:
print(*i[:3])
Not sure what you mean by "without builtin" functions, as that just seems silly. Find the max length to pad, then apply it as such:
from itertools import chain
data=[[2,124,123],[3,4,5]]
max_padding = max(len(str(el)) for el in chain.from_iterable(data))
for i in data:
print(' '.join([str(el).rjust(max_padding) for el in i]))
Gives:
2 124 123
3 4 5
If you actually want brackets around it, then it's easy enough to add them in...
Is the below doing what you want?
for i in data:
print("[" + ' '.join(str(x) for x in i) + "]")

Categories