Find first element in array that matches a specific condition in Swift - ios

Let's say I have an array like so:
[
["required": true],
["required": true],
["required": false],
["required": false],
["required": false],
["required": false],
["required": false]
]
I want to insert a new element into this array at the index where required first equals false (at position 2). I'm sure I could determine this using a basic for-each loop, e.g.:
var idx = 0
for (i, el) in myArray.enumerate() {
if el["required"] == false {
idx = i
break
}
}
But this doesn't seem very Swift-like. Is there a cleaner (i.e. less code) way of doing this in Swift 2? Perhaps something using filter or map?

How about this:
let idx = myArray.indexOf({$0["required"] == false})
Swift 3:
let idx = myArray.index(where: { $0["required"] == false })

let required = array.filter { $0["required"] == true }
let notRequired = array.filter { $0["required"] == false }
let result = required + [["required": true]] + notRequired

Related

How to insert data and tables into an existing one?

I have a trouble inserting new rows and tables into an already existing one.
Lets call the source SourceFile.lua and its simplified contents:
SourceFile = {};
SourceFile.list = {
BrandName1 = {
number = 10,
products = {
"Product1", 3,
"Product2", 4,
"Product3", 7,
},
},
BrandName2 = {
number = 5,
products = {
"Product1", 10,
"Product2", 3,
"Product3", 6,
},
},
-- and so on
}
I want to do something like this:
require 'SourceFile'
local myData = {
BrandName2 = { -- add new products for the existing brand
products = {
"Product4", 2,
},
},
MyBrandName1 = { -- add new brand
number = 12,
products = {
"MyProduct1", 21,
"MyProduct2", 95,
},
},
-- and so on
}
table.insert(SourceFile.list, myData)
However there's something wrong in my code and I get the following result (printed with inspect):
{
list = { {
BrandName2 = {
products = { "Product4", 2 }
},
MyBrandName1 = {
number = 12,
products = { "MyProduct1", 21, "MyProduct2", 95 }
}
},
BrandName1 = {
number = 10,
products = { "Product1", 3, "Product2", 4, "Product3", 7 }
},
BrandName2 = {
number = 5,
products = { "Product1", 10, "Product2", 3, "Product3", 6 }
}
}
}
What am I doing wrong?
I'm new to lua and pretty sure that it's something obvious, but not for me. Please, help me.
Addition
After these answers I've also found a way to insert new brand names one by one:
SourceFile.list.MyBrandName1 = {
number = 12,
products = {
"MyProduct1", 21,
"MyProduct2", 95,
},
}
This does not fully answer my question, but might be useful to someone new to lua.
table.insert adds its second argument to an array (its first argument). Your SourceFile.list is only supposed to have string keys, so it can't work as an array. You'll need a recursive function to merge the data from one table into the other:
local function meld(data, newData)
for k, v in pairs(newData) do
local oldValue = data[k]
if type(oldValue) ~= 'table' or type(v) ~= 'table' then
-- One of the values is not a table, so let's clobber the old value.
data[k] = v
else
-- Both are tables.
meld(oldValue, v)
end
end
end
meld(SourceFile.list, myData)
You are pushing a table of brandnames into a list of brandnames.
Which makes it a list of brandnames + table with brandnames.
table.insert(SourceFile.list, myData)
This inserts myData to SourceFile.list. myData is a table with brandnames.
SourceFile.list is also a table with brandnames.
List in list.
You have 2 choices to solve this:
Insert each brandname separately
Make a function to merge contents of myData to SourceFile.list

Metric math alarms: How can I use a for_each expression to loop over metrics within a dynamic block?

I am trying to create dynamic metric math alarms, that are configurable with a JSON.
I am struggling with looping over the metric alarm with a for_each expression as this is a loop within a loop.
Here is an example of what I am trying to do:
resource "aws_cloudwatch_metric_alarm" "Percentage_Alert" {
for_each = var.percentage_error_details
locals { alarm_details = each.value }
alarm_name = "${terraform.workspace}-${each.key}"
comparison_operator = local.alarm_details["Comparison_Operator"]
evaluation_periods = "1"
threshold = local.alarm_details["Threshold"]
metric_query {
id = "e1"
expression = local.alarm_details["Expression"]
label = local.alarm_details["Label"]
return_data = "true"
}
dynamic "metric_query" {
for metric in each.value["Metrics"]{
id = metric.key
metric_name = metric.value
period = local.alarm_details["Period"]
stat = local.alarm_details["Statistic"]
namespace = local.full_namespace
unit = "Count"
}
}
}
And this is the sample JSON
{
"locals": {
"Name": {
"Name": "metric_math",
"Metrics": {
"m1": "Sucess",
"m2": "Failure"
},
"Expression": "100*(m2/(m1+m2))",
"Threshold" : 1,
"Period": 25,
"Priority": "critical",
"Statistic": "Sum",
"Label": "label",
"Comparison_Operator": "GreaterThanOrEqualToThreshold"
}
}
}
And this is the error message i'm getting:
Error: Invalid block definition
On ../modules/cloudwatch/metriclogfilter/main.tf line 89: Either a quoted
string block label or an opening brace ("{") is expected here.
Any help would be much appreciated.

Shortest way to initialize a dictionary

Is there a terser way to declare and initialize a dictionary in F#?
let grid = Map.empty
.Add(0, true).Add(1, true).Add(2, true)
.Add(3, true).Add(4, false).Add(5, true)
.Add(6, true).Add(7, true).Add(8, true)
I use:
[0, true
1, false
2, true]
|> Map.ofList
#CaringDev's answer is good, but there's yet another consideration.
The elements of the tuple have key/value relation, so for best clarity I use the following definition:
let (=>) x y = x,y
This lets me write a very readable, self-documented code like this:
let myValue1 =
Map [
0 => true
1 => false
2 => false
]
Also, let makeMap x = new Map<_,_>(x) lets you write the code in another style, depending on your team's coding conventions:
let myValue2 =
[
0 => true
1 => false
2 => false
] |> makeMap

Sort table with gaps

I got a table which is not meant to be sorted in a way I need it to be sorted at a specific point.
Thus, I cannot sort the table while creation but have to sort it when needed.
Problem is, there are plenty gabs in the indeces and the Values I want to sort here are nested.
Simplified model:
table = {
[1] = { a = 1 , b = 31231, c = { c1 = "foo" , true } },
[8] = { a = 2 , b = 5231 , c = { c1 = "bar" , true } },
[92] = { a = 8 , b = 2 , c = { c1 ="asdgköbana" , false } },
}
Now I want to sort this table by length of c[1].
How can I do that in the fastest way? Length of table in first dimension will stay under 100 entries.
Indices don't need to be kept. So by a table with 3 entries, it's okay when last index is [3] after the portage. Basicly in this case, I only use the index to identifies neighbors, they have no prior use.
Using table as a variable kills the table library, which you need to get the sort function.
Try the code below. Note that it makes a new table to hold the sorted list but reuses the internal tables.
local t = {
[1] = { a = 1 , b = 31231, c = { c1 = "foo" , true } },
[8] = { a = 2 , b = 5231 , c = { c1 = "bar" , true } },
[92] = { a = 8 , b = 2 , c = { c1 ="asdgköbana" , false } },
}
local s = {}
for k,v in pairs(t) do
s[#s+1]=v
end
table.sort(s,function (a,b)
return #a.c.c1 < #b.c.c1
end)
for k,v in ipairs(s) do
print(k,v.a,v.c.c1)
end

how to populate nested tables in Lua?

This must be embarrassingly easy, but I can't find the solution: I have a text file with data in this form:
| 1 | 1 | A | X |
| | 2 | A | Z |
| | | B | Y |
I would like to process this data with Lua, so I need to have it in a structured (nested) table like this (I hope the indentation comes out right):
t = {
['1'] =
{
['1'] =
{
{
{ ['A'] = 'X' },
},
},
['2'] =
{
{
{ ['A'] = 'Z' },
{ ['B'] = 'Y' },
},
},
},
}
But I can't figure out how to go from A to B. The structure is already kind of there, but how can I read it into Lua?
This will definitely do the task for you.
tTable = {}
OldIDX, OldIDX2, bSwitched, bSwitched2 = 0, 0, false, false
for str in io.lines("txt.txt") do
local _, _, iDx, iDex, sIdx, sVal = str:find( "^%| ([%d|%s]?) %| ([%d|%s]?) %| (%S?) %| (%S?) %|$" )
if not tonumber(iDx) then iDx, bSwitched = OldIDX, true end
if not tonumber(iDex) then iDex, bSwitched2 = OldIDX2, true end
OldIDX, OldIDX2 = iDx, iDex
if not bSwitched then
tTable[iDx] = {}
end
if not bSwitched2 then
tTable[iDx][iDex] = {}
end
bSwitched, bSwitched2 = false, false
tTable[iDx][iDex][sIdx] = sVal
end
NOTE
The only thing you can change in the code is the name of the file. :)
EDIT
Seems like I was wrong, you did need some changes. Made them too.
Assuming you can read in a line and get to the individual items between the |'s, the algorithm would be something like this (pseudo code, I'll use col(n) to indicate the character in the n'th column for the current line):
1. store current indices for columns 1 and 2 (local vars)
2. read line (if no more lines, go to 7.)
3. if col(1) not empty - set the currentCol1 index to col(1)
a. if t[currentCol1] == nil, t[currentCol1] = {}
4. if col(2) not empty - set the currentCol2 index to col(2)
a. if t[currentCol1][currentCol2] == nil, t[currentCol1][currentCol2] = {}
5. set t[currentCol1][currentCol2][col(3)] = col(4)
6. go to step 2.
7. return t
I hope this is mostly self explanatory. Except for step 2 you shouldn't have problems going from pseudo-code to lua (and we don't know how you're getting to that data to help you with step 2). If you're not sure about the able operations, I'd suggest going over "Tables as arrays" and "Tables as dictionaries" from this lua-users tutorial.
As a side note - your example seems to be double-nesting the A=X,A=Z,B=Y inside two tables. I suspect that instead of:
['2'] =
{
{
{ ['A'] = 'Z' },
{ ['B'] = 'Y' },
},
},
you meant:
['2'] =
{
{ ['A'] = 'Z' },
{ ['B'] = 'Y' },
},
so that's what the pseudo code should get you.

Resources