Lua Variable, Table, For Loop Syntax - for-loop

Just saw this in the Lua self examples...
-- Example 24 -- Printing tables.
-- Simple way to print tables.
a={1,2,3,4,"five","elephant", "mouse"}
for i,v in pairs(a) do print(i,v) end
-------- Output ------
1 1
2 2
3 3
4 4
5 five
6 elephant
7 mouse
Press 'Enter' key for next example
I haven't seen this syntax before, for i,v in pairs(a) do print(i,v) end
Where did the v come into existence ?
Does the word in cause it to exist ?
By the same token, where does the i come into existence ?
Is this a syntax designed for tables ?
Thanks for any explanation.

pairs returns an iterator over all fields and their values
more exactly it's a function of table and previous seen index which returns pair of index and its value.
> t = {4,5,6}
> p = pairs(t)
> =p(t)
1 4
> =p(t,1)
2 5
> =p(t,2)
3 6
there are 2 options: iterate over every keys or just those which are integers:
pairs and ipairs functions
this loop is very similar to python's
l = [4,5,6]
for i, v in enumerate(l):
...
or
d = {"a":1, "b":2}
for k, v in d.iteritems():
...
if you know python (it looks like everyone knows it)

Related

Sorting/ordering values from smallest to biggest in an array

I have a formula like this : =ArrayFormula(sort(INDEX($B$1:$B$10,MATCH(E1,$A$1:$A$10,0))))
in columns A:B:
a 1
b 2
c 3
d 4
e 5
f 6
g 7
h 8
i 9
j 10
and
the data to convert in E:H
a c f e
f a c b
b a c d
I get the following results using the above formula
in columns L:O:
1 3 6 5
6 1 3 2
2 1 3 4
My desired output is like this:
1 3 5 6
1 2 3 6
1 2 3 4
I'd like to arrange the numbers from smallest to biggest in value. I can do this with additional helper cells. but if possible i'd like to get the same result without any additional cells. can i get a little help please? thanks.
To sort by row, use SORT BYROW. But unfortunately, nested array results aren't supported in BYROW. So, we need to JOIN and SPLIT the resulting array.
=ARRAYFORMULA(SPLIT(BYROW(your_formula,LAMBDA(row,JOIN("🌆",SORT(TRANSPOSE(row))))),"🌆"))
Here's another way using Makearray with Index to get the current row and Small to get the smallest, next smallest etc. within the row:
=ArrayFormula(makearray(3,4,lambda(r,c,small(index(vlookup(E1:H3,A1:B10,2,false),r,0),c))))
Or you could change the order (might be a little faster) as you don't need to vlookup the entire array, just the current row:
=ArrayFormula(makearray(3,4,lambda(r,c,small(vlookup(index(E1:H3,r,0),A1:B10,2,false),c))))
It's interesting (to me at any rate) that you can interrogate the row and column number of the current cell using Map or Scan, so this is also possible:
=ArrayFormula(map(E1:H3,lambda(cell,small(vlookup(index(E1:H3,row(cell),0),A1:B10,2,false),column(cell)-column(E:E)+1))))
Thanks to #JvdV for this insight (which may be obvious to some but wasn't to me) shown here in Excel.
try:
=INDEX(TRIM(SPLIT(FLATTEN(QUERY(QUERY(QUERY(SPLIT(FLATTEN(E1:H3&"×​"&ROW(E1:H3)), "​"),
"select max(Col1) group by Col1 pivot Col2"), "offset 1", 0),,9^9)), "×")))
or if you want numbers:
=INDEX(IFNA(VLOOKUP(TRIM(SPLIT(FLATTEN(QUERY(QUERY(QUERY(SPLIT(FLATTEN(E1:H3&"×​"&ROW(E1:H3)), "​"),
"select max(Col1) group by Col1 pivot Col2"), "offset 1", 0),,9^9)), "×")), A:B, 2, 0)))

Best approach for formula of matching values in sheet 2

I need to populate column A in sheet two based on multiple columns in sheet one.
For example, here are two of multiple conditions:
If columns A,B,C,D (of sheet 2) are all 5/6 then populate corresponding row in sheet one with "mid".
If columns A,B,C,D (of sheet 2) contain at least one 3 and L,M,O contain all 0s, populate "low".
I believe using SWITCH would make the most sense, unless someone can reccommend a simpler approach?
My main issue is with the syntax of writing this, I am getting a formula parse error:
=SWITCH(Sheet 1!G2:G&K2:K,ISBETWEEN(5,6),"mid")
Sheet 1
A B C D E F G H I J K L M N O
2 2 3 2 0 0 0 0
5 5 6 6
In row one of my example sheet 2 would get "mid" and row 2 would get "low"
try:
=ARRAYFORMULA(
IF( 4=LEN(REGEXREPLACE(FLATTEN(QUERY(TRANSPOSE(A1:D5),,9^9)), "[^5-6]+", )), "mid",
IF((4=LEN(REGEXREPLACE(FLATTEN(QUERY(TRANSPOSE(L1:O5),,9^9)), "[^0]+", )))*(REGEXMATCH(FLATTEN(QUERY(TRANSPOSE(A1:D5),,9^9)), "3")), "low", )))

How to extract vectors from a given condition matrix in Octave

I'm trying to extract a matrix with two columns. The first column is the data that I want to group into a vector, while the second column is information about the group.
A =
1 1
2 1
7 2
9 2
7 3
10 3
13 3
1 4
5 4
17 4
1 5
6 5
the result that i seek are
A1 =
1
2
A2 =
7
9
A3 =
7
10
13
A4=
1
5
17
A5 =
1
6
as an illustration, I used the eval function but it didn't give the results I wanted
Assuming that you don't actually need individually named separated variables, the following will put the values into separate cells of a cell array, each of which can be an arbitrary size and which can be then retrieved using cell index syntax. It makes used of logical indexing so that each iteration of the for loop assigns to that cell in B just the values from the first column of A that have the correct number in the second column of A.
num_cells = max (A(:,2));
B = cell (num_cells,1);
for idx = 1:max(A(:,2))
B(idx) = A((A(:,2)==idx),1);
end
B =
{
[1,1] =
1
2
[2,1] =
7
9
[3,1] =
7
10
13
[4,1] =
1
5
17
[5,1] =
1
6
}
Cell arrays are accessed a bit differently than normal numeric arrays. Array indexing (with ()) will return another cell, e.g.:
>> B(1)
ans =
{
[1,1] =
1
2
}
To get the contents of the cell so that you can work with them like any other variable, index them using {}.
>> B{1}
ans =
1
2
How it works:
Use max(A(:,2)) to find out how many array elements are going to be needed. A(:,2) uses subscript notation to indicate every value of A in column 2.
Create an empty cell array B with the right number of cells to contain the separated parts of A. This isn't strictly necessary, but with large amounts of data, things can slow down a lot if you keep adding on to the end of an array. Pre-allocating is usually better.
For each iteration of the for loop, it determines which elements in the 2nd column of A have the value matching the value of idx. This returns a logical array. For example, for the third time through the for loop, idx = 3, and:
>> A_index3 = A(:,2)==3
A_index3 =
0
0
0
0
1
1
1
0
0
0
0
0
That is a logical array of trues/falses indicating which elements equal 3. You are allowed to mix both logical and subscripts when indexing. So using this we can retrieve just those values from the first column:
A(A_index3, 1)
ans =
7
10
13
we get the same result if we do it in a single line without the A_index3 intermediate placeholder:
>> A(A(:,2)==3, 1)
ans =
7
10
13
Putting it in a for loop where 3 is replaced by the loop variable idx, and we assign the answer to the idx location in B, we get all of the values separated into different cells.

Count characters starting at zero?

I need to write a for-each loop that lists each character in
mystery_string with its index. Example below:
mystery_string= "Olivia," output would be:
0 O
1 l
2 i
3 v
4 i
5 a
I cannot use the range function on this problem.
This is my code, but the number starts at 1. What am I doing wrong?
mystery_string = "CS1301"
count = 0
for current_letter in mystery_string:
count = count + 1
print (count , current_letter)
I have been getting this as output:
1 C
2 S
3 1
4 3
5 0
6 1
but it needs to start at zero.
Just add the count (count += 1) after you print in the for loop
Note: Also, please format your code in a code block surrounded with a tick(`) or multiline code with 3 tick (```)
The pythonic way is to use enumerate() in such a case. This way you'll get both the index and the content of your string.
mystery_string = "CS1301"
for count, current_letter in enumerate(mystery_string):
print (count , current_letter)

Elixir: Return value from for loop

I have a requirement for a for loop in Elixir that returns a calculated value.
Here is my simple example:
a = 0
for i <- 1..10
do
a = a + 1
IO.inspect a
end
IO.inspect a
Here is the output:
warning: variable i is unused
Untitled 15:2
2
2
2
2
2
2
2
2
2
2
1
I know that i is unused and can be used in place of a in this example, but that's not the question. The question is how do you get the for loop to return the variable a = 10?
You cannot do it this way as variables in Elixir are immutable. What your code really does is create a new a inside the for on every iteration, and does not modify the outer a at all, so the outer a remains 1, while the inner one is always 2. For this pattern of initial value + updating the value for each iteration of an enumerable, you can use Enum.reduce/3:
# This code does exactly what your code would have done in a language with mutable variables.
# a is 0 initially
a = Enum.reduce 1..10, 0, fn i, a ->
new_a = a + 1
IO.inspect new_a
# we set a to new_a, which is a + 1 on every iteration
new_a
end
# a here is the final value of a
IO.inspect a
Output:
1
2
3
4
5
6
7
8
9
10
10

Resources