Lua table syntax - lua

This seems to be legitimate Lua syntax:
example = { ["dummy"] = "foobar"}
Why would you use the above and not simply:
example = { dummy = "foobar"}
They appear to functionally the same...

Because field names do not have to be identifiers: they can be any string, including strings having spaces, for instance.
The second statement is valid Lua syntax and is very convenient for field names that are identifiers.
Table keys do not have to be strings: they can actually be any value (except nil) and the [expr]=expr syntax for table entries allows the values of arbitrary expressions to be used as keys.

Related

Lua, using table of strings as keys to call values from different tables

What I want
ores = {"Bauxite", "Coal", "Hematite"}
properties={["Bauxite"]={name="Bauxite", density=1.2808},["Coal"]={name="Coal" , density=1.3465},["Quartz"]={name="Quartz" , density=2.6498},["Hematite"]={name="Hematite" , density=5.0398}}
system.print(properties.ores[1].name)
system.print(properties.ores[1].density)
Should Output
Bauxite
1.2808
This is a recurrent question regarding indexing tables by a value rather than by a constant string. You're currently using ((properties.ores)[1]).name; this is not parsed as properties.(ores[1]).name as you seem to have expected. That's because . is always followed by an identifier - a constant string - which is used to index the table. table.key is just shorthand for table["key"] for keys matching [a-zA-Z_][a-zA-Z0-9_]*. If you want to dynamically index a table with some expression, you have to use table[expr].
To fix your code, simply do:
system.print(properties[ores[1]].name)
system.print(properties[ores[1]].density)

How do i remove rows based on comma-separated list of values in a Power BI parameter in Power Query?

I have a list of data with a title column (among many other columns) and I have a Power BI parameter that has, for example, a value of "a,b,c". What I want to do is loop through the parameter's values and remove any rows that begin with those characters.
For example:
Title
a
b
c
d
Should become
Title
d
This comma separated list could have one value or it could have twenty. I know that I can turn the parameter into a list by using
parameterList = Text.Split(<parameter-name>,",")
but then I am unsure how to continue to use that to filter on. For one value I would just use
#"Filtered Rows" = Table.SelectRows(#"Table", each Text.StartsWith([key], <value-to-filter-on>))
but that only allows one value.
EDIT: I may have worded my original question poorly. The comma separated values in the parameterList can be any number of characters (e.g.: a,abcd,foo,bar) and I want to see if the value in [key] starts with that string of characters.
Try using List.Contains to check whether the starting character is in the parameter list.
each List.Contains(parameterList, Text.Start([key], 1)
Edit: Since you've changed the requirement, try this:
Table.SelectRows(
#"Table",
(C) => not List.AnyTrue(
List.Transform(
parameterList,
each Text.StartsWith(C[key], _)
)
)
)
For each row, this transforms the parameterList into a list of true/false values by checking if the current key starts with each text string in the list. If any are true, then List.AnyTrue returns true and we choose not to select that row.
Since you want to filter out all the values from the parameter, you can use something like:
= Table.SelectRows(#"Changed Type", each List.Contains(Parameter1,Text.Start([Title],1))=false)
Another way to do this would be to create a custom column in the table, which has the first character of title:
= Table.AddColumn(#"Changed Type", "FirstChar", each Text.Start([Title],1))
and then use this field in the filter step:
= Table.SelectRows(#"Added Custom", each List.Contains(Parameter1,[FirstChar])=false)
I tested this with a small sample set and it seems to be running fine. You can test both and see if it helps with the performance. If you are still facing performance issues, it would probably be easier if you can share the pbix file.
This seems to work fairly well:
= List.Select(Source[Title], each Text.Contains(Parameter1,Text.Start(_,1))=false)
Replace Source with the name of your table and Parameter1 with the name of your Parameter.

Xtext optional ordering with comma

I have a DSL that looks like JSON and I need to support optional ordering of the elements. For example:
{
'id': 'someid',
'position' : 'someposition',
'operand' : 'someoperand'
}
In order to support any ordering of 'id', 'position', and 'operand' tokens with valid commas, I had to do something like this:
Block returns Block:
{Block}
'{'
members+=BlockMember (',' members+=BlockMember)*
'}'
;
BlockMember returns BlockMember:
blockId=BlockId | position=BlockPosition | operand=Operand
;
The problem is that each element (id, position, operand) is both mandatory as well as only once. With this grammar, I have some issues:
You can define the elements more than once (which also screws up LSP
content assist later).
I can't enforce the mandatory requirement.
It creates an inferred EMF model where a Block has a 'members' collection instead of well defined properties. This means later to parse a Block, I have to iterate the member.
Because it needs to be well-formed JSON, the last property cannot have a comma
I know I can do this if I enforce a specific order and look for the comma. What I would like to do however is have the optional ordering with commas between (except for last) without introducing a 'members' that creates the issues listed above.
Is there a technique to do this?

Realm not query string field with whitespace

I have such function in my data source:
func getAllFood(by type: String) -> [UserFoodInformation] {
var findedFood = [UserFoodInformation]()
findedFood.append(contentsOf: baseUserFoodDataSource.getAllFood(by: type))
let predicate = NSPredicate(format: "foodType == %#", type)
let resultOfSearching = dataBase.objects(AddedUserFood.self).filter(predicate).sorted(byKeyPath: "name")
for searchedFood in resultOfSearching {
findedFood.append(searchedFood)
}
return findedFood
}
When I try to query with string that consist whitespace, I have no result, but if I query with simple one-word parameter, everything goes fine. Why is that? Can I have a string field in Realm that consists multiple words?
The predicate you're using is looking for objects whose foodType property is equal to the type string that is passed in. Only those objects whose property is exactly equal to that string will match. If you want to perform some other form of matching you'll need to use something other than the equality operator. BEGINSWITH, CONTAINS, ENDSWITH and LIKE are the comparison operators that Realm supports on string fields.
Can I have a string field in Realm that consists multiple words?
String fields can contain any string values. The supported comparison operators don't have the concept of a "word", though, so if you want to do filtering using that concept you'll likely need to do further work on your part. Depending on your use case, I can see a couple of ways to go about it:
Use CONTAINS to find any objects whose foodType properties contains the given type string.
Parse the string into structured data that you store in your model. For instance, it may make sense to store a List<FoodType> rather than a String for the foodType property.
There are likely other options, but they depend on details of what it is you're trying to achieve that you've not shared.

Rails query by number of digits in field

I have a Rails app with a table: "clients". the clients table has a field: phone. phone data type is string. I'm using postgresql. I would like to write a query which selects all clients which have a phone value containing more than 10 digits. phone does not have a specific format:
+1 781-658-2687
+1 (207) 846-3332
2067891111
(345)222-777
123.234.3443
etc.
I've been trying variations of the following:
Client.where("LENGTH(REGEXP_REPLACE(phone,'[^\d]', '')) > 10")
Any help would be great.
You almost have it but you're missing the 'g' option to regexp_replace, from the fine manual:
The regexp_replace function provides substitution of new text for substrings that match POSIX regular expression patterns. [...] The flags parameter is an optional text string containing zero or more single-letter flags that change the function's behavior. Flag i specifies case-insensitive matching, while flag g specifies replacement of each matching substring rather than only the first one.
So regexp_replace(string, pattern, replacement) behaves like Ruby's String#sub whereas regexp_replace(string, pattern, replacement, 'g') behaves like Ruby's String#gsub.
You'll also need to get a \d through your double-quoted Ruby string all the way down to PostgreSQL so you'll need to say \\d in your Ruby. Things tend to get messy when everyone wants to use the same escape character.
This should do what you want:
Client.where("LENGTH(REGEXP_REPLACE(phone, '[^\\d]', '', 'g')) > 10")
# --------------------------------------------^^---------^^^
Try this:
phone_number.gsub(/[^\d]/, '').length

Resources