I have this lambda map formula (simplified for the question). It works well, but chatgpt suggested me that I can change IF(COUNTA(a;b;c;d;e)>0;" // ";"") for IF(COUNTA(a:e)>0;" // ";"") so i can simplify lambda variable ranges. But when I tried in sheets, it automatically change (a:e) for (A:E), and coloured, so I suppose that is interpreted as columns A:E (and I get a #value error.
=MAP(
AP3:AP;Q3:Q;AR3:AR;AT3:AT;BF3:BF;
LAMBDA(a;b;c;d;e;
TEXTJOIN(" / "; TRUE;
a;
b;
c;
d;
e;
) & IF(COUNTA(a;b;c;d;e)>0;" // ";"")
)
)
Is it possible to achieve what I want and get a:e as variable range? It's a large formula and i could simplify things a lot.
Thanks!
What about if you try to do the same but with BYROW?. It will process all your ranges row by row, and with curly brackets you stack them (if you already have HSTACK you can do the same without the curly brackets). If I understand correctly you could do something like this:
=BYROW(
{AP3:AP\Q3:Q\AR3:AR\AT3:AT\BF3:BF};
LAMBDA(r;
TEXTJOIN(" / "; TRUE;
r
) & IF(COUNTA(r)>0;" // ";"")
)
)
Related
I see several posts about making a string in to a lua table, but my problem is a little different [I think] because there is an additional dimension to the table.
I have a table of tables saved as a file [i have no issue reading the file to a string].
let's say we start from this point:
local tot = "{{1,2,3}, {4,5,6}}"
When I try the answers from other users I end up with:
local OneDtable = {"{1,2,3}, {4,5,6}"}
This is not what i want.
how can i properly create a table, that contains those tables as entries?
Desired result:
TwoDtable = {{1,2,3}, {4,5,6}}
Thanks in advance
You can use the load function to read the content of your string as Lua code.
local myArray = "{{1,2,3}, {4,5,6}}"
local convert = "myTable = " .. myArray
local convertFunction = load(convert)
convertFunction()
print(myTable[1][1])
Now, myTable has the values in a 2-dimensional array.
For a quick solution I suggest going with the load hack, but be aware that this only works if your code happens to be formatted as a Lua table already. Otherwise, you'd have to parse the string yourself.
For example, you could try using lpeg to build a recursive parser. I built something very similar a while ago:
local lpeg = require 'lpeg'
local name = lpeg.R('az')^1 / '\0'
local space = lpeg.S('\t ')^1
local function compile_tuple(...)
return string.char(select('#', ...)) .. table.concat{...}
end
local expression = lpeg.P {
'e';
e = name + lpeg.V 't';
t = '(' * ((lpeg.V 'e' * ',' * space)^0 * lpeg.V 'e') / compile_tuple * ')';
}
local compiled = expression:match '(foo, (a, b), bar)'
print(compiled:byte(1, -1))
Its purpose is to parse things in quotes like the example string (foo, (a, b), bar) and turn it into a binary string describing the structure; most of that happens in the compile_tuple function though, so it should be easy to modify it to do what you want.
What you'd have to adapt:
change name for number (and change the pattern accordingly to lpeg.R('09')^1, without the / '\0')
change the compile_tuple function to a build_table function (local function build_tanle(...) return {...} end should do the trick)
Try it out and see if something else needs to be changed; I might have missed something.
You can read the lpeg manual here if you're curious about how this stuff works.
I have written a test utility function aequals (assert equals) that expects an actual result and an expected result as arguments. I use it like this:
aequals(fib(8), 21);
But now I have a function with multiple return values:
function stuff() return 1,2,3 end
I want to check its function by either checking it all together:
aequals( stuff(), {1,2,3} );
but this does not work because only "1" is left on the stack for aequals.
Or at least one after the other:
aequals( stuff()[1], 1 );
aequals( stuff()[2], 2 );
aequals( stuff()[3], 3 );
but this gives a syntax error, because stuff returns a tuple, not an array/table.
I tried to fix this using the array-constructor, which supposed to make a tuple into an array/table.
aequals( {stuff()}[1], 1 );
why this is a syntax error I can not understand.
I circumvented this by defining helper functions which I am sure are already in Lua, if I only knew where to look:
function arg0(a,b,c) return a end;
function arg1(a,b,c) return b end;
function arg2(a,b,c) return c end;
aequals( arg0(stuff()), 1 );
While this works it is quite cumbersome and it would be so much nicer to have the whole check in one line... but how?
function stuff() return 1,2,3 end
aequals( stuff(), {1,2,3} );
Used like this, the list returned by stuff() will be reduced to the first element, because stuff() is not the last expression in that expression list.
You could swap the table and stuff() to circumvent this in a simple manner.
aequals({1,2,3}, stuff())
Or use tables as suggested by Egor's comment.
From Lua 5.3 Reference Manual 3.4 Expressions
Both function calls and vararg expressions can result in multiple
values. If a function call is used as a statement (see §3.3.6), then
its return list is adjusted to zero elements, thus discarding all
returned values. If an expression is used as the last (or the only)
element of a list of expressions, then no adjustment is made (unless
the expression is enclosed in parentheses). In all other contexts, Lua
adjusts the result list to one element, either discarding all values
except the first one or adding a single nil if there are no values.
I have a formula calculating a number :
F = SUMIFS(Besoins!$D$2:$D$999;Besoins!$C$2:$C$999;C$1;Besoins!$B$2:$B$999;$B5)
What I try to do then is to print either the result :
if F > 0, or "-" if F = 0
So I try with the IF function :
=IF(F=0;"-";?)
I don't know what to use to print the correct result when it is false. Anyone know how I could do it?
Unfortunately, you cannot set a variable in a spreadsheet formula; that is, you cannot actually set the name F to your SUM expression there. You can either write:
=IF(SUM(Besoins!$D$2:$D$999;Besoins!$C$2:$C$999;C$1;Besoins!$B$2:$B$999;$B5)=0,"-",SUM(Besoins!$D$2:$D$999;Besoins!$C$2:$C$999;C$1;Besoins!$B$2:$B$999;$B5))
Or you could store SUM(Besoins!$D$2:$D$999;Besoins!$C$2:$C$999;C$1;Besoins!$B$2:$B$999;$B5) in one cell (for the sake of argument, cell A1) and in another cell, write:
=IF(A1=0,"-",A1)
I'm having a problem with lua's table.concat, and suspect it is just my ignorance, but cannot find a verbose answer to why I'm getting this behavior.
> t1 = {"foo", "bar", "nod"}
> t2 = {["foo"]="one", ["bar"]="two", ["nod"]="yes"}
> table.concat(t1)
foobarnod
> table.concat(t2)
The table.concat run on t2 provides no results. I suspect this is because the keys are strings instead of integers (index values), but I'm not sure why that matters.
I'm looking for A) why table.concat doesn't accept string keys, and/or B) a workaround that would allow me to concatenate a variable number of table values in a handful of lines, without specifying the key names.
Because that's what table.concat is documented as doing.
Given an array where all elements are strings or numbers, returns table[i]..sep..table[i+1] ··· sep..table[j]. The default value for sep is the empty string, the default for i is 1, and the default for j is the length of the table. If i is greater than j, returns the empty string.
Non-array tables have no defined order so table.concat wouldn't be all that helpful then anyway.
You can write your own, inefficient, table concat function easily enough.
function pconcat(tab)
local ctab, n = {}, =1
for _, v in pairs(tab) do
ctab[n] = v
n = n + 1
end
return table.concat(ctab)
end
You could also use next manually to do the concat, etc. yourself if you wanted to construct the string yourself (though that's probably less efficient then the above version).
I have been learning about metatables in Lua and I wanted to implement range operators as in Ruby, so I used this model
debug.setmetatable(1, {
__concat = function(a, b)
if a > b then
error(table.concat({
"attempt to create a range of values with a",
"minimum larger than the maximum"
}, " "))
elseif a == b then
return a
else
return unpack((function(nStart,nEnd)
local nTable = {}
for it = nStart,nEnd do
table.insert(nTable, it)
end
return nTable
end)(a, b))
end
end
})
print(6 .. 6)
But it seems that that it continues to use the default behavior. Is there any way to get this to work? I am aware that I could make a function to emulate the behavior and call it with range(n,n2) or similar but that defeats the purpose. Thanks.
Please see section 3.4.5 of the Lua 5.2 manual.
The string concatenation operator in Lua is denoted by two dots ('..'). If both operands are strings or numbers, then they are converted to strings according to the rules mentioned in §3.4.2. Otherwise, the __concat metamethod is called (see §2.4).
If you want to change this behavior, look into lvm.c, specifically the luaV_concat function.