Related
I have a cell array of strings of length 3
headers_ca =
{
[1,1] = time
[1,2] = x
[1,3] = y
}
I want to create a struct that mimics a python dict, with the values in headers_ca as keys (fieldnames in Octave) and an initializer value ival for all entries.
It would be a struct, since even dict exists in octave, it has been deprecated.
I could do (brute force) s = struct("time", ival, "x", ival, "y", ival);
What is the most concise way to do this?
I know I can do a for loop.
Can it be avoided?
I would be working with much longer cell arrays.
You can use struct or cell2struct to create the structure.
headers_ca = {'time','x','y'};
headers_ca(2, :) = {ival};
s = struct(headers_ca{:});
headers_ca = {'time','x','y'};
ivals = repmat({ival}, numel(headers_ca), 1);
s = cell2struct(ivals, headers_ca);
I have a random array of numbers 1 to five occurring in ramdom sometimes [1,1,1,1,2,2] etc. I am tasked with finding the value with highest occurrence all the the time regardless. I achieved that in javascript like below using a library called ramda here . After reading the documentation, i went with a solution like below.
// filter out duplication in array that way you can get the uniq represented numbers
const uniqueItems = R.uniq(params);
// use the unique numbers as keys and create a new array of object
const mappedItemsWithRepresentations = map((a) => ({ color: a, rep: params.filter(b => b === a).length }), uniqueItems);
// and then finally, select the item with highest rep and return it key
const maxRepItem = mappedItemsWithRepresentations.reduce((acc, curr) => acc.rep > curr.rep ? acc : curr, []);
return maxRepItem.key; // gives me the correct value i need
However, reading through more in the documentation and going through the example here, i realised there is a way i can combine the logic above and simply with ramda. I tried numerous attempt possible and the closest i could get are below.
const getMaxRep = curry(pipe(uniq, map((a) => ({ color: a, rep: filter(b => b === a).length })), pipe(max(pathEq("rep")), tap(console.log))));
console.log("Max Rep here", getMaxRep(params));
I also tried utilising the reduced feature here, all to no avail. Please how do i arrange achieve that ? Any help will be appreciated.
Ramda has R.countBy to get the number of occurrences. You can convert the resulting object of country to pairs [value, count], and then reduce it to find the pair with the highest count:
const { pipe, countBy, identity, toPairs, reduce, maxBy, last, head } = R
const fn = pipe(
countBy(identity), // count the occurrences
toPairs, // convert to pairs of [value, count]
reduce(maxBy(last), [0, 0]), // reduce to find the maximum occurrence
head, // get the actual value
Number, // convert back to an number
)
const arr = [1,1,1,1,2,2]
const result = fn(arr)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
A slight variation on this idea that collects values with the same count to an array. This will handle cases in which the frequency of several items is identical:
const { pipe, countBy, identity, toPairs, invert, reduce, maxBy, last, head, map } = R
const fn = pipe(
countBy(identity), // count the occurrences
invert, // combine all values with the same count
toPairs, // convert to pairs of [value, count]
reduce(maxBy(head), [0, 0]), // reduce to find the maximum occurrence
last, // get the actual values
map(Number), // convert back to numbers
)
const arr = [1,1,1,1,2,2,3,3,3,3]
const result = fn(arr)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
nice use case, try this:
const maxReduce = reduce(maxBy(last), [0,0])
const getMaxRep = pipe(countBy(identity), toPairs, maxReduce, head)
console.log(getMaxRep([1,1,1,1,2,2]))
countBy is a really nice start, sadly Ramda don't support reduce for object but we can convert to an array of arrays using toPairs function and finish the work.
It's not entirely clear to me what it is you're asking for.
But it might be something like this:
const maxRep = pipe (
countBy (identity),
toPairs,
map (zipObj(['color', 'rep'])),
reduce (maxBy (prop ('rep')), {rep: -Infinity}),
)
const params = [1, 2, 3, 4, 2, 3, 5, 2, 3, 2, 1, 1, 4, 5, 5, 3, 2, 5, 1, 5, 2]
console .log (
maxRep (params)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
<script> const {pipe, countBy, identity, toPairs, map, zipObj, reduce, maxBy, prop} = R </script>
We start with a list of values drawn from {1, 2, 3, 4, 5}, occuring in some random, multiply-occuring order.
With countBy(identity) we change the original list into something like
{"1": 4, "2": 6, "3": 4, "4": 2, "5": 5}
with the counts associated with each entry.
toPairs formats that as an array like
[["1", 4], ["2", 6], ["3", 4], ["4", 2], ["5", 5]]
(You could also use Object.entries here.)
Then by calling map (zipObj (['color', 'rep'])), we turn this into
[{"color": "1", "rep": 4}, {"color": "2", "rep": 6}, ...]
Finally, we reduce the result, using maxBy (prop ('rep')), which chooses the one with the maximum rep value. For the initial value to the max call, we create a dummy object, {rep: -Infinity} that will compare less than any in your list.
If you wanted to also keep that final intermediate structure, you could rename that function to makeReps, dropping off the last function in the pipeline, and then making a new maxRep out of it.
Then you could call
const reps = makeResps (params)
const maxVal = maxRep (reps)
and use both.
But all this presupposes that the value with color and rep properties is what you need. If you just need the count then the other solutions already here handle that fine.
The question
Given a MiniZinc array of strings:
int: numStats;
set of int: Stats = 1..numStats;
array[Stats] of string: statNames;
... with data loaded from a MiniZinc data file:
numStats = 3;
statNames = ["HEALTH", "ARMOR", "MANA"];
How can one look up the index of a specific string in the array? For example, that ARMOR is located at position 2.
The context
I need to find an optimal selection of items with regard to some constraints on their stats. This information is stored in a 2D array declared as follows:
int: numItems;
set of int: Items = 1..numItems;
array[Items, Stats] of float: itemStats;
So in order to write a constraint on, say, the minimum amount of ARMOR obtained through the selected items, I need to know that ARMOR has index 2 in the inner array.
Since the data file is generated by an external program, and the number and order of stats are dynamic, I cannot hardcode the indices in the constraints.
One solution (that won't work in my case)
The MiniZinc tutorial uses an interesting trick to achieve something similar:
set of int: Colors = 1..3;
int: red = 1;
int: yellow = 2;
int: blue = 3;
array[Colors] of string: name = ["red", "yellow", "blue"];
var Colors: x;
constraint x != red;
output [ name[fix(x)] ];
Unfortunately, as variable declarations are not allowed in MiniZinc data files, this trick won't work in my case.
You can write your own custom function to get the index of a string within a string array:
function int: getIndexOfString(string: str,
array[int] of string: string_array) =
sum( [ if str = string_array[i]
then i
else 0 endif
| i in index_set(string_array) ]
);
In this function I create an array of integers where the integer at position i either equals the index of str if string_array[i]=str and 0 otherwise. For instance, for your sample string array ["HEALTH", "ARMOR", "MANA"] and str ARMOR the resulting int array will be [0,2,0].
This is why I can simply sum over the int array to get the index of the string. If the string does not occur, the return value is 0, which is fine since indices in MiniZinc start with 1 by default.
Here is how you can call the function above for your first example:
int: numStats;
set of int: Stats = 1..numStats;
array[Stats] of string: statNames;
numStats = 3;
statNames = ["HEALTH", "ARMOR", "MANA"];
var int: indexOfArmor;
constraint
indexOfArmor = getIndexOfString("ARMOR",statNames);
solve satisfy;
Note however that the function above is limited and has some flaws. First, if you have multiple occurrences of the string in the array, then you will receive an invalid index (the sum of all indices where str occurred). Also, if you have your own index set for your string array (say (2..6)), then you will need to adapt the function.
Another, cleaner option is to write a function that uses a recursive helper function:
% main function
function int: index_of(string: elem, array[int] of string: elements) =
let {
int: index = length(elements);
} in % calls the helper function with the last index
get_index(elem, elements, index)
;
% recursive helper function
function int: get_index(string: elem, array[int] of string: elements, int: index) =
if index == 0
then -1 % the element was not found (base case of recursion)
elseif elements[index] == elem
then index % the element was found
else
get_index(elem, elements, index - 1) % continue searching
endif
;
The helper function iterates recursively over the array, starting from the last element, and when it finds the element, it returns the index. If the element was not found in the array, then -1 is returned. Alternatively, you can also throw an assertion following the suggestion of Patrick Trentin by replacing then -1 with then assert(false, "unknown element: " + elem).
An example of calling this function:
set of int: Customers = 1..5;
array[Customers] of string: ids = ["a-1", "a-2", "a-3", "a-4", "a-5"];
var int: index = index_of("a-3", ids);
var int: unknown_index = index_of("x-3", ids);
where index will be assigned 3 and unknown_index will be -1.
An alternative approach to that presented by Andrea Rendl-Pitrey, is the following one:
array[int] of string: statNames = array1d(10..12, ["HEALTH", "ARMOR", "MANA"]);
var int: indexOfArmor =
sum([i | i in index_set(statNames) where statNames[i] = "ARMOR"]);
solve satisfy;
output [
"indexOfArmor=", show(indexOfArmor), "\n",
];
which outputs:
~$ mzn2fzn example.mzn ; flatzinc example.fzn
indexOfArmor = 11;
----------
note: that var can be dropped from the declaration of indexOfArmor, since the index can be statically computed. I kept it here only for output purposes.
A better solution is to declare a new predicate:
predicate index_of_str_in_array(var int: idx,
string: str,
array[int] of string: arr) =
assert(
not exists(i in index_set(arr), j in index_set(arr))
(i != j /\ arr[i] = str /\ arr[j] = str),
"input string occurs at multiple locations",
assert(
exists(i in index_set(arr))
(arr[i] = str),
"input string does not occur in the input array",
exists(i in index_set(arr))
(arr[i] = str /\ i = idx)
));
which enforces both of the following conditions:
str occurs at least once in arr
str does not occur multiple times in arr
e.g
predicate index_of_str_in_array(var int: idx,
string: str,
array[int] of string: arr) =
...
array[10..13] of string: statNames =
array1d(10..13, ["HEALTH", "ARMOR", "MANA", "ATTACK"]);
var int: indexOfArmor;
constraint index_of_str_in_array(indexOfArmor, "ARMOR", statNames);
solve satisfy;
output [
"indexOfArmor=", show(indexOfArmor), "\n",
];
outputs
~$ mzn2fzn example.mzn ; flatzinc example.fzn
indexOfArmor = 11;
----------
If one changes statNames in the following way
array[10..13] of string: statNames =
array1d(10..13, ["HEALTH", "ARMOR", "MANA", "ARMOR"]);
then mzn2fzn detects an assertion violation:
~$ mzn2fzn example.mzn ; flatzinc example.fzn
MiniZinc: evaluation error:
example.mzn:24:
in call 'index_of_str_in_array'
example.mzn:4:
in call 'assert'
Assertion failed: input string occurs at multiple locations
flatzinc:
example.fzn: cannot open input file: No such file
A similar result would be obtained by searching for the index of a string that does not occur in the array. This condition can of course be removed if not necessary.
DISCLAIMER: older versions of mzn2fzn don't seem to check that the declared index-set of an array of strings variable matches the index-set of an array of strings literal that is being assigned to it. This rule is enforced on newer versions, as it is also valid for other data types.
According to this other post on Stackoverflow there is no way of converting strings to integers in MiniZinc, only the other way around. You need to first pre process your data in some other language and turn it into integers. You can however turn those integers into string once you are done in MiniZinc.
You can however load MiniZinc files instead of data files if you would like. Use the include syntax to include any .mzn file.
I have a strange issue with the following code :
var dict = ["KEY" : [1, 2]]
println(dict["KEY"]) // Output is "Optional([1, 2])"
println(dict["KEY"]!) // Output is "[1, 2]"
dict["KEY"]!.append(3) // Error : '(String, Array<Int>)' does not have a member named 'append'
dict["KEY"]! += 3 // Error : type 'DictionaryIndex<String, Array<Int>>' does not conform to protocol 'StringLiteralConvertible'
My goal is to transform the dict variable from ["KEY" : [1, 2]] to ["KEY" : [1, 2, 3]].
I have probably missed something but I don't see what.
Firstly, from apple docs:
Conversely, if you assign an array or a dictionary to a constant, that
array or dictionary is immutable, and its size and contents cannot be
changed.
I think if you assign an array as a value of key within dictionary it goes the same way.
In addition Swift collections are copied whenever they are assigned or passed as a parameter.
If you really want to change array in dict, I guess you may create new array with appended items for example and reassign the value of dict
var arrayInit = [1, 2]
var dict = ["KEY" : arrayInit]
//somewhere
var array = dict["KEY"]!
array.append(3)
dict["KEY"] = array;
println(dict["KEY"]!) // Output is "[1, 2]"
That will do it...
import Cocoa
import Foundation
var dict = ["KEY" : [1, 2]]
println(dict["KEY"]) // Output is "Optional([1, 2])"
println(dict["KEY"]!) // Output is "[1, 2]"
var array = dict["KEY"]!
array.append(3)
array += 3
dict["KEY"] = array
I am having trouble figuring out how to get the length of a matrix within a matrix within a matrix (nested depth of 3). So what the code is doing in short is... looks to see if the publisher is already in the array, then it either adds a new column in the array with a new publisher and the corresponding system, or adds the new system to the existing array publisher
output[k][1] is the publisher array
output[k][2][l] is the system
where the first [] is the amount of different publishers
and the second [] is the amount of different systems within the same publisher
So how would I find out what the length of the third deep array is?
function reviewPubCount()
local output = {}
local k = 0
for i = 1, #keys do
if string.find(tostring(keys[i]), '_') then
key = Split(tostring(keys[i]), '_')
for j = 1, #reviewer_code do
if key[1] == reviewer_code[j] and key[1] ~= '' then
k = k + 1
output[k] = {}
-- output[k] = reviewer_code[j]
for l = 1, k do
if output[l][1] == reviewer_code[j] then
ltable = output[l][2]
temp = table.getn(ltable)
output[l][2][temp+1] = key[2]
else
output[k][1] = reviewer_code[j]
output[k][2][1] = key[2]
end
end
end
end
end
end
return output
end
The code has been fixed here for future reference: http://codepad.org/3di3BOD2#output
You should be able to replace table.getn(t) with #t (it's deprecated in Lua 5.1 and removed in Lua 5.2); instead of this:
ltable = output[l][2]
temp = table.getn(ltable)
output[l][2][temp+1] = key[2]
try this:
output[l][2][#output[l][2]+1] = key[2]
or this:
table.insert(output[l][2], key[2])