Python itertools.combinations: how to obtain the indices of the combined numbers within the combinations at the same time - arrays

According to the question presented here: Python itertools.combinations: how to obtain the indices of the combined numbers, given the following code:
import itertools
my_list = [7, 5, 5, 4]
pairs = list(itertools.combinations(my_list , 2))
#pairs = [(7, 5), (7, 5), (7, 4), (5, 5), (5, 4), (5, 4)]
indexes = list(itertools.combinations(enumerate(my_list ), 2)
#indexes = [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)]
Is there any way to obtain pairs and indexes in a single line so I can have a lower complexity in my code (e.g. using enumerate or something likewise)?

#Maf - try this, this is as #jonsharpe suggested earlier, use zip:
from pprint import pprint
from itertools import combinations
my_list = [7, 5, 5, 4]
>>> pprint(list(zip(combinations(enumerate(my_list),2), combinations(my_list,2))))
[(((0, 7), (1, 5)), (7, 5)),
(((0, 7), (2, 5)), (7, 5)),
(((0, 7), (3, 4)), (7, 4)),
(((1, 5), (2, 5)), (5, 5)),
(((1, 5), (3, 4)), (5, 4)),
(((2, 5), (3, 4)), (5, 4))]

(Explicit is better than implicit. Simple is better than complex.)
I would use list-comprehension for its flexiblity:
list((x, (x[0][1], x[1][1])) for x in list(combinations(enumerate(my_list), 2)))
This can be further extended using the likes of opertor.itemgetter.
Also, the idea is to run use the iterator only once, so that the method can potentially be applied to other non-deterministic iterators as well, say, an yield from random.choices.

Related

Grid of all elements of an arbitrarily sized matrix in Julia

I have an n*m sized array A, and I would like to create a grid of its elements. The output should look something like:
B = (A[1,1], A[2,1]
A[1,1], A[2,2]
...
A[1,1], A[2,m]
A[1,2], A[2,1]
A[1,2], A[2,2]
...
A[1,2], A[2,m]
...
A[n,1], A[n,m])
My first approach would be to do something like this:
A = [1 5;
2 6;
3 7;
4 8]
B = collect(Iterators.product(A))
However, this only returns
4×2 Matrix{Tuple{Int64}}:
(1,) (5,)
(2,) (6,)
(3,) (7,)
(4,) (8,)
Instead of the desired output above.
Any ideas?
Noone on the discourse.julialang.org link suggested:
hcat(repeat(A[:,1], inner=size(A,1)),repeat(A[:,2], outer=size(A,1)))
giving:
16×2 Matrix{Int64}:
1 5
1 6
1 7
1 8
2 5
2 6
2 7
2 8
3 5
3 6
3 7
3 8
4 5
4 6
4 7
4 8
One possible way could be:
julia> [Iterators.product(eachcol(A)...)...;]
16-element Vector{Tuple{Int64, Int64}}:
(1, 5)
(2, 5)
(3, 5)
(4, 5)
(1, 6)
(2, 6)
(3, 6)
(4, 6)
(1, 7)
(2, 7)
(3, 7)
(4, 7)
(1, 8)
(2, 8)
(3, 8)
(4, 8)
It was already answered by #DNF here:
https://discourse.julialang.org/t/grid-of-all-elements-of-an-arbitrarily-sized-matrix/89024/3
The essence of it:
This works for any matrix, but here is an explicit example:
A = [1 5;
2 6;
3 7;
4 8]
The solution is:
Iterators.product(A[:, 1], A[:, 2]) |> collect
Resulting in
4×4 Matrix{Tuple{Int64, Int64}}:
(1, 5) (1, 6) (1, 7) (1, 8)
(2, 5) (2, 6) (2, 7) (2, 8)
(3, 5) (3, 6) (3, 7) (3, 8)
(4, 5) (4, 6) (4, 7) (4, 8)
If you do not want to specify each column explicitly:
Iterators.product(eachcol(A)...) |> collect
In case you prefer a long vector instead of the above result, redefine it as a vector:
Iterators.product(eachcol(A)...) |> collect |> vec
The three dots are the splat operator, which "unpacks" the result of eachcol(A).

How to convert RBG data into a Image

I'm doing a easy cybersecurity challenge where I'm given a data file with only RBG codes like the following ones:
[(0, 0, 2), (0, 0, 2), (0, 0, 2), (0, 0, 2), (0, 0, 2), (0, 0, 2), (0, 0, 2), (0, 0, 2), (0, 0, 2), (1, 1, 3), (1, 1, 3), (1, 1, 3), (0, 0, 2), (0, 0, 2), (0, 0, 2), (1, 1, 3), (0, 0, 2), (0, 0, 2), (1, 1, 3), (1, 1, 3), (1, 1, 3), (1, 1, 3), (0, 0, 2), (0, 0, 2), (1, 1, 3)]
As you may wonder, the file is much wider and longer and I don't know how I should convert all this RBG data into an image. I tried using a python script in a Lubuntu1204 but it still gave me some errors and I didnt get the image I was looking for.
Thanks for the help in advance!

create an array based on grouping (and conditions) from an array

So, I have the following array (structured as Array{Tuple{Int,Float64,Int,Int},1} but it can also be an Array of Arrays) and where the first element of the tuple is an ID and the second is a number indicating a cost. What i want to do is to group by ID and then take the cost difference between the cheapest and the second cheapest cost for such ID, if there is no second cost, the cost difference should be typemax(Float64) -firstcost. Regarding the third and fourth elements of the Tuple, I want to keep those of the firstcost (or minimum cost in that sense).
Example of what I have
(1, 223.2, 2, 2)
(1, 253.2, 3, 2)
(2, 220.0, 4, 6)
(3, 110.0, 1, 4)
(3, 100.0, 3, 8)
Example of what I want:
(1, 30.0, 2, 2)
(2, typemax(Float64)-220.0, 4, 6)
(3,10.0, 3, 8)
This is one way of doing it:
A = [(1, 223.2, 2, 2), (1, 253.2, 3, 2), (2, 220.0, 4, 6), (3, 110.0, 1, 4), (3, 100.0, 3, 8)]
function f(a)
aux(b::Vector) = (b[1][1], (length(b) == 1 ? typemax(Float64) : b[2][2]) - b[1][2], b[1][3:4]...)
sort([aux(sort(filter(x -> x[1] == i, a))) for i in Set(map(first, a))])
end
#show f(A)
There's SplitApplyCombine.jl, which implements (unsurprisingly) a split-apply-combine logic like that found in DataFrames. This is an example where I would stay away from simple one-liners / short solution and write things out more explicitly in the interest of making the code readable and understandable if someone else (or you yourself in a few months time!) reads it:
julia> tups = [(1, 223.2, 2, 2)
(1, 253.2, 3, 2)
(2, 220.0, 4, 6)
(3, 110.0, 1, 4)
(3, 100.0, 3, 8)]
5-element Array{Tuple{Int64,Float64,Int64,Int64},1}:
(1, 223.2, 2, 2)
(1, 253.2, 3, 2)
(2, 220.0, 4, 6)
(3, 110.0, 1, 4)
(3, 100.0, 3, 8)
julia> using SplitApplyCombine
julia> function my_fun(x) # function to apply
if length(x) == 1
return (x[1][1], typemax(Float64) - x[1][2], x[1][3], x[1][4])
else
return (x[1][1], -diff(sort(getindex.(x, 2), rev = true)[1:2]), x[1][4])
end
end
my_fun (generic function with 1 method)
julia> [my_fun(x) for x in group(first, tups)] # apply function group wise
3-element Array{Tuple{Int64,Any,Int64,Vararg{Int64,N} where N},1}:
(2, Inf, 4, 6)
(3, [10.0], 4)
(1, [30.0], 2)
If performance is a concern you might want to think about my_fun and do some profiling to see if and how you can improve it - the only thing I've done here is to use diff to subtract the first from the second element of the sorted array to avoid sorting twice.

Sort array of objects in numpy?

How can I efficiently sort an array of objects on two or more attributes in Numpy?
class Obj():
def __init__(self,a,b):
self.a = a
self.b = b
arr = np.array([],dtype=Obj)
for i in range(10):
arr = np.append(arr,Obj(i, 10-i))
arr_sort = np.sort(arr, order=a,b) ???
Thx, Willem-Jan
The order parameter only applies to structured arrays:
In [383]: arr=np.zeros((10,),dtype='i,i')
In [385]: for i in range(10):
...: arr[i] = (i,10-i)
In [386]: arr
Out[386]:
array([(0, 10), (1, 9), (2, 8), (3, 7), (4, 6), (5, 5), (6, 4), (7, 3), (8, 2), (9, 1)],
dtype=[('f0', '<i4'), ('f1', '<i4')])
In [387]: np.sort(arr, order=['f0','f1'])
Out[387]:
array([(0, 10), (1, 9), (2, 8), (3, 7), (4, 6), (5, 5), (6, 4), (7, 3), (8, 2), (9, 1)],
dtype=[('f0', '<i4'), ('f1', '<i4')])
In [388]: np.sort(arr, order=['f1','f0'])
Out[388]:
array([(9, 1), (8, 2), (7, 3), (6, 4), (5, 5), (4, 6), (3, 7), (2, 8),
(1, 9), (0, 10)],
dtype=[('f0', '<i4'), ('f1', '<i4')])
With a 2d array, lexsort provides a similar 'ordered' sort
In [402]: arr=np.column_stack((np.arange(10),10-np.arange(10)))
In [403]: np.lexsort((arr[:,1],arr[:,0]))
Out[403]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int32)
In [404]: np.lexsort((arr[:,0],arr[:,1]))
Out[404]: array([9, 8, 7, 6, 5, 4, 3, 2, 1, 0], dtype=int32)
With your object array, I could extract the attributes into either of these structures:
In [407]: np.array([(a.a, a.b) for a in arr])
Out[407]:
array([[ 0, 10],
[ 1, 9],
[ 2, 8],
....
[ 7, 3],
[ 8, 2],
[ 9, 1]])
In [408]: np.array([(a.a, a.b) for a in arr],dtype='i,i')
Out[408]:
array([(0, 10), (1, 9), (2, 8), (3, 7), (4, 6), (5, 5), (6, 4), (7, 3),
(8, 2), (9, 1)],
dtype=[('f0', '<i4'), ('f1', '<i4')])
The Python sorted function will work on arr (or its list equivalent)
In [421]: arr
Out[421]:
array([<__main__.Obj object at 0xb0f2d24c>,
<__main__.Obj object at 0xb0f2dc0c>,
....
<__main__.Obj object at 0xb0f35ecc>], dtype=object)
In [422]: sorted(arr, key=lambda a: (a.b,a.a))
Out[422]:
[<__main__.Obj at 0xb0f35ecc>,
<__main__.Obj at 0xb0f3570c>,
...
<__main__.Obj at 0xb0f2dc0c>,
<__main__.Obj at 0xb0f2d24c>]
Your Obj class is missing a nice __str__ method. I have to use something like [(i.a, i.b) for i in arr] to see the values of the arr elements.
As I stated in the comment, for this example, a list is much nice than an object array.
In [423]: alist=[]
In [424]: for i in range(10):
...: alist.append(Obj(i,10-i))
list append is faster than the repeated array append. And object arrays don't add much functionality compared to a list, especially when 1d, and the objects are custom classes like this. You can't do any math on arr, and as you can see, sorting isn't any easier.

How to sort an Array of Tuples?

How do you implement (or create) an array sort of a list of tuples?
The following was gleaned from my code. Essentially I created an array of tuples
and populated it via for loop; after which I tried to sort it.
var myStringArray: (String,Int)[]? = nil
...
myStringArray += (kind,number)
...
myStringArray.sort{$0 > $1}
This is what Xcode gave me before I could build:
test.swift:57:9: '(String, Int)[]?' does not have a member named
'sort'
You have two problems. First, myStringArray is an Optional, you must "unwrap" it before you can call methods on it. Second, there is no > operator for tuples, you must do the comparison yourself
if let myStringArray = myStringArray {
myStringArray.sort { $0.0 == $1.0 ? $0.1 > $1.1 : $0.0 > $1.0 }
}
Actually, what I was looking for, is the tuple with the largest integer value:
var myStringArray: (String,Int)[]? = nil
...
println("myStringArray: \(myStringArray)\n")
myStringArray!.sort {$0.1 > $1.1}
println("myStringArray: \(myStringArray)\n")
...
Original:
myStringArray: [(One, 1), (Square, 1), (Square, 4), (Square, 9),
(Square, 16), (Square, 25), (Prime, 2), (Prime, 3), (Prime, 5),
(Prime, 7), (Prime, 11), (Prime, 13), (Fibonacci, 1), (Fibonacci, 1),
(Fibonacci, 2), (Fibonacci, 3), (Fibonacci, 5), (Fibonacci, 8)]
Sorted:
myStringArray: [(Square, 25), (Square, 16), (Prime, 13), (Prime, 11),
(Square, 9), (Fibonacci, 8), (Prime, 7), (Prime, 5), (Fibonacci, 5),
(Square, 4), (Prime, 3), (Fibonacci, 3), (Prime, 2), (Fibonacci, 2),
(One, 1), (Square, 1), (Fibonacci, 1), (Fibonacci, 1)]
...so it's the "square" having the largest integer: 25.

Resources