how to iteratively pick out one attribute in an object, and stack the rest attributes into an array, Python3 - arrays

I have an object with a, b, c, d four attributes. Each attribute is a vector.
I want to pick one attribute out and assemble the rest attributes into an 2-dimensional array. And do it for every attribute.
For example:
import numpy as np
class Obj:
def __init__(self, a, b, c, d):
self.a = a
self.b = b
self.c = c
self.d = d
b = np.array([1,1,1,1,1])
a = 0*b
c = 2*b
d = 3*b
obj1 = Obj(a, b, c, d)
# take attribute a for example
pick = obj1.a
x = np.column_stack((obj1.b, obj1.c, obj1.d))
# then pick attribute b, c, and d, one at a time, and assemble the rest.
Is there a way to iterate over all attributes? Because in real case, there may be 40 attributes.
Thanks

Related

Minizinc: set enumerated set of options based on array position, as opposed to set of options for all array positions

I am familiar with such approaches as
set of int: RANGE = 1..5;
enum OPTS = {A,B,C};
array[RANGE] of var OPTS = result;
but what about when I would like to specify the OPTS for each position in RANGE? Something that looks like
[{A,B,C},{A,B},{A,B,C,D},{B,D},{A}]
then generate result[n] so that it picks one of the available options at n.
I've tried with the following model but a model inconsistency is detected.
set of int: RANGE = 1..5;
enum OPTS = {A,B,C,D};
array[RANGE] of set of OPTS: t = [{A,B,C},{A,B},{A,B,C,D},{B,D},{A}];
array[RANGE] of var OPTS: result;
constraint forall(i in RANGE)(
forall(j in t[i])(
result[i] = j
)
);
output [show(result)]
with a possible result being [B,A,B,D,A] - the last position result[5] cannot be anything other than A.
I try to use the Minizinc manuals but I cannot decipher how to use examples within the specifications eg https://www.minizinc.org/doc-2.4.3/en/spec.html#set-operations, which presuppose other knowledge (e.g. how to interpret the syntax) that I could spend countless hours trying to hunt down an explanation for on my level, since searching this stuff seems to be really unfruitful.
Thanks!
If I understand you correctly you can use set of OPTS to construct the array of OPTS, here called t (you cannot call it output since it's a reserved word). Note that as you presented the problem, it's not a var but a constant array so you don't need the var keyword when you construct the array.
set of int: RANGE = 1..5;
enum OPTS = {A,B,C,D};
array[RANGE] of set of OPTS: t = [{A,B,C},{A,B},{A,B,C,D},{B,D},{A}];
Update
Here's a model for the updated question. The trick here is that t[i] defines the valid domain of result[i], and you can simply use in for this.
set of int: RANGE = 1..5;
enum OPTS = {A,B,C,D};
array[RANGE] of set of OPTS: t = [{A,B,C},{A,B},{A,B,C,D},{B,D},{A}];
array[RANGE] of var OPTS: result;
constraint
forall(i in RANGE) (
% ensure that result[i] only takes the values in t[i]
result[i] in t[i]
)
;
output [show(result)]
There are 48 solutions to this problem, such as:
[A, A, A, B, A]
----------
[B, A, A, B, A]
----------
[C, A, A, B, A]
----------
[A, B, A, B, A]
----------
[B, B, A, B, A]
----------
[C, B, A, B, A]
----------
[A, A, B, B, A]
----------
...

How to insert NaN in an array if it is missing values that are present in another array?

Assume I have two arrays:
A = [850;950;1000;1050;1100];
B = [850;950;1000;1100];
Here B is missing the value 1050 that is present in array A. As I later would like to compare A and B logically I would like to fill this missing place with a NaN thus giving me
B = [850;950;1000;NaN;1100];
What is the fastest way to do this in Matlab?
I would create a copy of A, and NaN out any values which aren't a member of B. This is easier than inserting NaNs in the correct places of B...
C = A;
C( ~ismember( A, B ) ) = NaN;
Optionally, you can assign B = C at the end.
Alternatively you can avoid copying all of A, and just assign the index to a variable, this is purely a preference thing...
idx = ~ismember( A, B );
B = A;
B( idx ) = NaN;

How to convert nested arrays to a group of one-element arrays

Sorry the title isn't very clear.
What would be the best way to convert
[a, [b, c], [d, e, f], g]
(or other similarly group of nested arrays) into
[a, b, d, g], [a, b, e, g], [a, b, f, g], [a, c, d, g], ..., [a, c, f, g]
?
Since you now learned Smalltalk, I suggest you take a look at a recursive solution:
https://stackoverflow.com/a/9878747/1396822 .
or an iterative one:
Generating all combinations from collections in Smalltalk
You now know that it's called a cartesian product, so you shall be able to find other answers on SO.
New solution
This is a non-recursive solution written in Smalltalk. The receiver is the collection of subsequences such as [a, [b, c], [d, e, f], g]. For the sake of simplicity the code below assumes that all entries in the receiver array are arrays, so the proper receiver would be [[a], [b, c], [d, e, f], [g]] instead, which in Smalltalk is written #((a) (b c) (d e f) (g)).
1. selections
2. | selections indexes index |
3. selections := OrderedCollection new.
4. indexes := Array new: self size withAll: 1.
5. [| group |
6. group := (1 to: self size) collect: [:i | (self at: i) at: (indexes at: i)].
7. selections add: group.
8. index := (1 to: self size)
findLast: [:i | (indexes at: i) < (self at: i) size]
ifAbsent: nil.
9. index notNil]
10. whileTrue: [
11. indexes at: index put: (indexes at: index) + 1.
12. index + 1 to: self size do: [:i | indexes at: i put: 1]].
13. ^selections
Comments
Method name
Temporary declaration
Initialize the output
Start by selecting the first element of every subgroup
Do .. while
Collect one element from each subgroup at the current indexes
Keep the group just created
Find the last index which can be incremented
Stop if there is none (this will jump to 13)
If there is one such index...
Increment that index
Reset all following indexes to 1 (this will get back to 6)
Answer with the result
I've done it in python but this process can be applied to all programming language because are only two loops:
arr = ["a", ["b", "c"], ["d", "e", "f"], "g"]
first = arr[1] # b, c
second = arr[2] # d, e, f
for j in first:
for k in second:
print(list((arr[0], j, k, arr[-1])))

Perl: array splitting and complex merging

I have the following string A B C D E F G H I J. I want to make an array out of it, so I use this
my #string = split/(\W)/, $text;
It works ok, and I get an array of 20 lines looking like this:
A
B
C
D
...
Now, I want to split this array in a given number of pieces (let's say 4 in this case), thus resulting I imagine in 4 smaller arrays of 5 lines each, looking like this #1 = A, ,B, ,C , #2 = ,D, ,E,, #3 = F, ,G, ,H and #4 = ,I, ,J,.
Finally, I want to interleave these 4 arrays in order to get an output array in which I first have the first line of each array, the the second line of each array, and so on... the final thing looking like this :
A
F
D
I
B
G
E
J
C
H
How to achieve this?
To make a slice of an array in Perl:
my #oldArray = (a, ,b, ,c, ,d, ,e, ,f, ,g, h, ,i, ,j, );
my #newArray1 = #oldArray[elemIndex1,elemIndex2,elemIndexN];
OR
my #newArray1 = #oldArray[firstElemIndex..lastElemIndex]
Where elemIndex is the index of the element you want in the newArray array.
firstElemIndex..lastElemIndex is used when you want consecutive indexes to be in the sliced array.
To add elements at the end of an array:
push(#interleavedArray,$newArray1[elemIndex]);
Where $newArray1[elemIndex] is the element from #newArray1 you want to add to #interleavedArray
To add elements in order:
Just do a for loop:
for my $index (0..3){
push(#interleavedArray,$newArray1[$index]);
push(#interleavedArray,$newArray2[$index]);
push(#interleavedArray,$newArray3[$index]);
push(#interleavedArray,$newArray4[$index]);
}

How to always make a copy for an affectation?

I have defined a Matrix module as follows:
module Matrix =
struct
type 'a matrix = 'a array array
let make (nr: int) (nc: int) (init: 'a) : 'a matrix =
let result = Array.make nr (Array.make nc init) in
for i = 0 to nr - 1 do
result.(i) <- Array.make nc init
done;
result
let copy (m: 'a matrix) : 'a matrix =
let l = nbrows m in
if l = 0 then m else
let result = Array.make l m.(0) in
for i = 0 to l - 1 do
result.(i) <- Array.copy m.(i)
done;
result
...
Then I could code for instance let mat = Matrix.make 5 5 100. The advantage of defining Matrix module is to hide the type of its components. For example, I may later want to define a matrix with 'a list list or with map. I will just need to change this module, but not the code who uses this module.
But one problem I realize is that, if I do let m1 = m0 in ..., m1 and m0 will share a same physical item: any change to m1 will affect m0. Actually this is the purpose of the copy function. But is there a way to let the module always call copy for an affectation?
The worse is for a function let f (m: 'a matrix) = ..., any change inside f to m will affect the outer parameter who past its value to m. Is there a way to avoid f to do so?
You can easily define shadow copies, something along:
type 'a m =
| Shared of 'a matrix
| Matrix of 'a array array
and 'a matrix = {
mutable m : 'a m;
}
let copy_matrix m = [... YOUR CODE FOR COPY ...]
(* Shadow copy *)
let copy matrix =
{ m = Shared matrix }
let rec content m =
match m.m with
| Shared m -> content m
| Matrix m -> m
let write m x y k =
let c = match m.m with
| Shared matrix ->
(* Break the shared chain & copy the initial shared matrix *)
let c = copy_matrix (content matrix) in
m.m <- Matrix c;
c
| Matrix m -> m in
c.(x).(y) <- k
When you write let m1 = m0, the names m1 and m0 denote the same object. This is not an assignment, it is a binding of a value to a name. Since the expression after the = sign is a simple name, both names m1 and m0 have the same value bound to them.
If you want to make a copy of a mutable data structure, you must request that copy explicitly.
If you want to be able to pass data around without having to modify it, this data must be immutable. This, indeed, is a key reason to use immutable data. When you use mutable data, you need to think carefully about sharing between data structures and who is responsible for copying when needed.
While you can reorganize any data structure to be immutable, dense matrices are not an example where immutability shines, because immutable representations of dense matrices tend to require rather more memory and more processing time.

Resources