How to populate multidimensional array in Perl? - arrays

I'm getting a Use of uninitialized value error. I don't know if I'm populating my multidimensional array correctly.
my #matrix;
for (my $i=1; $i<=3;$i++){
$matrix[$i][0] = 4;
}
for (my $j=1; $j<=3;$j++){
$matrix[0][$j] = 4;
}
print $matrix[0][0];
I don't understand why this doesn't work. The way I wrote it, the matrix is supposed to populate like so:
1 0
2 0
3 0
0 1
0 2
0 3

You're populating $matrix[1][0] and $matrix[0][1], but you don't store anything in $matrix[0][0].

Perl arrays start at 0 - try
my $i = 0

Related

How to dynamically create array and assign value in TCL

I want to create array dynamically and assign value to it. e.g.
set num 0
foreach i {1 2 3} {
set count$i(sp) {$num}
incr num
set count$i(ep) [expr $num+1]
}
When I ran your sample code, this error comes up:
can't read "i(sp)": variable isn't array
which is because the $i(sp) part of count$i(sp) looks like a reference to an existing array i.
You'll want to isolate $i from (sp) with curly brackets:
set num 0
foreach i {1 2 3} {
set count${i}(sp) {$num}
incr num
set count${i}(ep) [expr $num+1]
}
which creates three arrays:
tcl8.6.8> parray count1
count1(ep) = 2
count1(sp) = $num
tcl8.6.8> parray count2
count2(ep) = 3
count2(sp) = $num
tcl8.6.8> parray count3
count3(ep) = 4
count3(sp) = $num
Note above that curly brackets around $num use the literal string $num.
You'll want to remove those curly brackets:
set num 0
foreach i {1 2 3} {
set count${i}(sp) $num
incr num
set count${i}(ep) [expr $num+1]
}
tcl8.6.8> parray count1
count1(ep) = 2
count1(sp) = 0
tcl8.6.8> parray count2
count2(ep) = 3
count2(sp) = 1
tcl8.6.8> parray count3
count3(ep) = 4
count3(sp) = 2
However, please explain exactly what you mean by "dynamically creating a Tcl array". Do you really want three separate arrays or could you have one array with more names, like this:
set num 0
foreach i {1 2 3} {
set count($i,sp) $num
incr num
set count($i,ep) [expr $num+1]
}
tcl8.6.8> parray count
count(1,ep) = 2
count(1,sp) = 0
count(2,ep) = 3
count(2,sp) = 1
count(3,ep) = 4
count(3,sp) = 2
If you can avoid using a dynamic variable name like that, do so; they're often more trouble than they're worth. (You can use “composite” element names like $i,sp instead.) Otherwise — perhaps because of other code that accesses the array — the simplest way of handling them is to use upvar to make an alias to the variable with a fixed name. In particular, upvar 0 makes an alias to a variable in the same scope:
set num 0
foreach i {1 2 3} {
upvar 0 count$i ary
set ary(sp) {$num}
incr num
set ary(ep) [expr $num+1]
}
The only problem with upvar 0 is that you can't really undo it; that's why you almost always only use it within a procedure so the aliasing goes away naturally when the procedure exits.
Variable aliases are extremely efficient within the context of a procedure, substantially more so than using compound variable names in multiple places.
Also, {$num} looks suspicious. It's not wrong code in that it has a correct interpretation, but might not do what you expect and is often indicative of a problem, as $num isn't substituted. You might prefer [list $num].
You might enjoy using a dict instead of an array:
set count {}
set num 0
foreach i {1 2 3} {
dict set count $i sp $num
incr num
dict set count $i ep [expr {$num + 1}]
}
set count ;# -> 1 {sp 0 ep 2} 2 {sp 1 ep 3} 3 {sp 2 ep 4}
dict get $count 3 ep ;# -> 4

How can I find the nonzero values in a MATLAB cells array?

The following code generates an cell array Index [1x29], where each cell is an array [29x6]:
for i = 1 : size(P1_cell,1)
for j = 1 : size(P1_cell,2)
[Lia,Lib] = ismember(P1_cell{i,j},PATTERNS_FOR_ERANOS_cell{1},'rows');
Index1(i,j) = Lib % 29x6
end
Index{i} = Index1; % 1x29
end
How can I find the nonzero values in Index array?, i.e. generate an array with the number of non-zero values in each row of the Index1 array. I tried the following loop, but it doesn't work, it creates conflict with the previous one:
for i = 1 : length(Index)
for j = 1 : length(Index)
Non_ceros = length(find(Index{:,i}(j,:))); %% I just need the length of the find function output
end
end
I need help, Thanks in advance.
The nnz() (number of non-zeros) function can be used to evaluate the number of non-zero elements. To obtain the specific positive values you can index the array by using the indices returned by the find() function. I used some random test data but it should work for 29 by 6 sized arrays as well.
%Random test data%
Index{1} = [5 2 3 0 zeros(1,25)];
Index{2} = [9 2 3 1 zeros(1,25)];
Index{3} = [5 5 5 5 zeros(1,25)];
%Initializing and array to count the number of zeroes%
Non_Zero_Counts = zeros(length(Index),1);
for Row_Index = 1: length(Index)
%Evaluating the number of positive values%
Array = Index{Row_Index};
Non_Zero_Counts(Row_Index) = nnz(Array);
%Retrieving the positive values%
Positive_Indices = find(Array);
PositiveElements{Row_Index} = Array(Positive_Indices);
disp(Non_Zero_Counts(Row_Index) + " Non-Zero Elements ");
disp(PositiveElements{Row_Index});
end
Ran using MATLAB R2019b
for i = 1 : length(Index)
for j = 1 : length(Index)
Non_ceros(i,j) = nnz(Index{:,i}(j,:));
end
end

Multidimensional array to string with each sub-array on new line

I'm trying to convert a multidimensional array like this:
var array = [["ID","Cue","Target","InitialCopyLen","InitialCopyStrict","NumStudied","NumTested","NumDropped","studyCountLen","testCountLen","studyCountStrict","testCountStrict","finaltestLen","finaltestStrict"],["bl","AGLUK","JAW","0","0","0","0","0","0","0","0","0","0","0"],["bl","AKI","MONEY","0","0","0","0","0","0","0","0","0","0","0"]];
to something like this (as a string):
ID Cue Target InitialCopyLen InitialCopyStrict NumStudied NumTested NumDropped studyCountLen testCountLen studyCountStrict testCountStrict finaltestLen finaltestStrict
bl AGLUK JAW 0 0 0 0 0 0 0 0 0 0 0
bl AKI MONEY 0 0 0 0 0 0 0 0 0 0 0
I tried converting to a string first, then using a replace function:
var newString = array.toString(array);
newString = newString.replace(/.{14}/g, '$&\n');
But obviously this just does every 14th character, and I need every 14th comma.
I then thought about something like this:
var i;
var commaCount = 0;
for (i = 0; i < newString.length; i++) {
if (i == ","){
commaCount++
if (commaCount == "14"){
// INSERT NEW LINE HERE
}
}
}
x.innerHTML = newString;
But perhaps there is a smarter way to do this? I basically want to convert the entire big array into a string, with each sub-array on its own line.
Inspite of iterating through every element in the inner array ,You can use for-each loop to separately convert each part of array to String.
for(var element : array){
str = element.toString();
System.out.println(str);
}
System.out.println() will take care of "\n"
I found the answer:
array.forEach(function(element) {
x.innerHTML += element + "<br>";
});`

How can I copy array from a Matlab struct array with fields to a struct of arrays

I currently have a struct of arrays:
t2 =
cotrain_idx: [7x1 double]
trvate_idx: [7x1 double]
conf_param: 0
is_target: 0
orig_idx: 0
I also have an struct array with fields:
t3 =
1x7 struct array with fields:
type
latency
urevent
ImageName
isTarget
isAccurate
origEventIdx
I would like to copy all the elements comprising t3.isTarget to t2.is_target. However all my attempts result in errors:
t2.is_target(:)=t3(:).isTarget;
seems to onlt copy the first element, even though t3(:).isTarget clearly returns all 7 elements:
>>> t3(:).isTarget
ans =
0
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
Is there something obvious that I'm missing here? If I have to, I can copy the elements in one at a time, but I expect Matlab has a more efficient way to do this.
You can try the following, with a simplified version of you strcture:
t2.a1=123
t3(1).isTarget=1
t3(2).isTarget=2
t3(3).isTarget=3
t2.isTarget=[t3.isTarget]
You ca access to all the element of the t3.isTarget field by using []
Hope this helps.

Dual array correspondance

I just found myself in a position where I have two arrays in Tcl.
I'm given $W_Array and $P_Array.
I need to traverse through one array not knowing what the size of each one is before hand, and execute a command only when there is a value for both arrays. Yes the array lengths could be different.
What is the best way of doing this?
The other answers jumped to using lists, I presume you mean Tcl's array, which are also called hash maps or associative arrays.
I think you're asking for something like:
array set a1 {a 1 b 2 c 3 d 4 e 5}
array set a2 {z 0 x 1 b 2 e 99}
foreach n [array names a1] {
if {[info exists a2($n)]} {
puts "Do something with $a1($n) and $a2($n)"
}
}
# FOREACH LOOP RESULTS IN THESE TWO PRINTOUTS
Do something with 5 and 99
Do something with 2 and 2
Not sure exactly what you mean by "a value for both arrays", but tcl's foreach supports iteration over multiple arrays at once... so you can say e.g.
foreach w $W_Array p $P_Array {
if {$w == $val && $p == $val} {
...
}
}
When the arrays are not of the same length, foreach will return all values from the longest array and the empty value {} for the missing elements in any shorter arrays.
Use llength command to find out if the arrays contain a value.
if {[llength $W_Array] > 0 && [llength $P_Array] > 0} {
# Do something
}

Resources