I would like to use length of provided array inside parameters list. I tried
def find(xs: Array[Double], m:Int = xs.length*2) = ???
,but xs is not accessible for m parameter.
Is it possible to do that? How?
When defining default values of arguments, you can refer only to variables in the previous argument lists. Therefore, you need two argument lists:
def find(xs: Array[Double])(m: Int = xs.size * 2) = ???
Then you can call it as follows:
find(Array(1, 2, 3))(6)
and
find(Array(1, 2, 3))()
In this case an ugly alternative is to use an invalid length as the default:
def find(xs: Array[Double], _m: Int = -1) = {
val m = if (_m >= 0) _m else xs.length
Related
Problem Statement
I will try to elaborate the case by means of a scenario. Lets take this question for instance.
Link to question: https://leetcode.com/problems/remove-element/
Given an array nums and a value target, remove all instances of
that value in-place and return the new length.
Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.
Example: Given nums = [0,1,2,2,3,0,4,2], target = 2; the output =
5 (number of elements not equal to target) and modify the array to
[0,1,3,0,4]
The order of elements can be changed. It doesn't matter what you leave
beyond the new length.
My Approach
Step-1: Identify all the elements which are equal to the given target and move them to right hand side of the array while maintaining a counter.
Step-2: Drop all the elements from right.
Step-3: return (n - counter), where n is the array length and counter is the number of elements equal to target.
Below is the implementation of the same:
object RemoveElement {
// Link to question: https://leetcode.com/problems/remove-element/
def main(args: Array[String]): Unit = {
var nums = Array(3,2,2,3)
val target = 3
val result = removeElement(nums, target)
// nums = nums.dropRight(_.equals(target)) // POINT 1
println(s"Result: ${result}, Modified Array: [${nums.mkString(", ")}]")
}
def removeElement(nums: Array[Int], target: Int): Int = {
val n = nums.length
var left, counter = 0
var right = n - 1
while(left < right){
if(nums(left) != target){
left += 1
}
else {
// Find position of the elements which is not equal to target
if(nums(right) == target){
counter += 1
right -= 1
}
else{
// Swap the elements
counter += 1
val temp = nums(left)
nums(left) = nums(right)
nums(right) = temp
left += 1
right -= 1
}
}
}
// nums.dropWhile(_.equals(target)) // POINT 2
// nums = nums.dropRight(_.equals(target)) // POINT 3
return (n - counter)
}
}
POINT - 1: Makes absolute sense as the array nums is in the scope of main method, therefore, the statement would work as charm.
POINT - 2: These lines has no impact to the array nums.
POINT - 3: Gives error. I understand that the input argument (array nums) is of type val (i.e. passed by reference, and hence immutable within the scope of the method removeElement).
If I had an option of creating a new array, there wouldn't be any issue. But if I am required to return the modified array by adding/removing the elements (like in this question) to the calling method, how do I achieve that in Scala?
To make the case more generic, what is the way by which we can modify the input collections (passed as arguments) in Scala methods?
P.S.: If I do not remove elements from the input array itself, LeetCode fails my submission with below message:
How do I modify an input array passed to a method by reference?
Scala does not support pass-by-reference. The default is pass-by-value (or more precisely, a special case of pass-by-value which is sometimes known as call-by-object, call-by-sharing, or call-by-object-sharing). Scala also supports call-by-name.
So, you simply cannot pass an array to a method by reference in Scala. You will have to use another language which supports pass-by-reference such as C# (with the ref keyword) or C++. (Note that Java also doesn't support pass-by-reference.)
Something like this
object Solution {
def removeElement(nums: Array[Int], `val`: Int): Int = {
var p: Int = 0
nums.foreach(v => {
if (v != `val`) {
nums(p) = v
p += 1
}
})
p
}
}
The below code is written in scala,
val Array(f, t) = readLine().trim().split(" +").map(_.toInt)
I am not able to comprehend val Array(f, t).
To me, Array is class. Due to that, We can only create the object and with that object, we can access the function of the class. Or else We can access the static methods of the Array class without creating an object for it.
-- scala
def main(args: Array[String]): Unit = {
val n = readInt
val m = readInt
val f = Array.ofDim[Int](100000)
Arrays.fill(f, -1)
for (e <- 1 to m) {
val Array(f, t) = readLine().trim().split(" +").map(_.toInt)
// Code continues
}
}
That is called pattern matching (for example you can check this at Extractors). The code you mentioned means that please assign the first (index 0) value in the array resulting to f, assign the second (index 1) element to t and there should not be more or less values in the array. Both f and t are fresh variables.
You also mentioned the confusion with the val Array(...) syntax. It translates to the following method: scala.Array.unapplySeq[T](x:Array[T])
I have a function that processes an individual data set, and stores the outcome metrics in a data set like so:
trial_data.output_metric_a.value_1 = 2;
...
trial_1 = trial_data;
This function is applied to a number of different trials and are stored as an array struct:
% trial_1.output_metric_a.value_1 = 4
% trial_2.output_metric_a.value_1 = 2
trials = [trial_1 ; trial_2];
Is it possible to get averages and standard deviations of the sub-field values
without looping through the data structure?
Ideally:
mean_trials = mean(trials)
mean_trials.output_metric_a.value_1 == 3 % true
A possible loop implementation to solve this could be (obviously this leaves much to be desired):
output_metric_a_value_1 = [];
...
for i:length(trials)
output_metric_a_value_1(end+1) = trials(i).output_metric_a.value_1;
... % For each output metric and value
end
mean_trials.output_metric_a.value_1 = mean(output_metric_a_value_1);
You can convert the main struct to cell, then operate on the contents:
% your data base:
trial_1.output_metric_a.value_1 = 4
trial_2.output_metric_a.value_1 = 2
trials = [trial_1 ; trial_2];
% convert to cell:
Ctrials=struct2cell(trials);
Atrials=[Ctrials{:}];
meanTrials=mean([Atrials.value_1])
meanTrials=
3
Special Solution (not-nested struct > array)
As already mentioned, aiming for just one level of struct fields (not nested) one can basically go for a one-liner:
sarr_mean = cellfun(#(fn) mean([sarr.(fn)]), fieldnames(sarr))
Remark: In the not-nested case, there is not really a need to assign the resulting array back to a struct. If required, you can do it analogously to the full solution below.
Full Solution (nested struct > nested struct)
However, with arbitrarily nested arrays, I suggest to use a function such as the following:
% f... function handle
% s... nested struct array
function sarr_res = nestedSarrFun(f, s)
if isstruct(s)
% get fieldnames:
fns = fieldnames(s);
% get content:
con = cellfun(#(fn) nestedSarrFun(f, [s.(fn)]), ...
fns, 'UniformOutput', false);
% create return struct
fnsCon = reshape([fns(:), con(:)]', [1,2*numel(fns)]);
sarr_res = struct(fnsCon{:});
else
sarr_res = f(s);
end
end
Usage Example
Define example struct array and apply mean via nestedSarrFun:
% define example struct array "sarr" with fields
% .foo.bar1
% .bar2
% .dings
sarr = struct();
sarr(1).foo.bar1 = 2;
sarr(1).foo.bar2 = 7;
sarr(1).dings = 1;
sarr(2).foo.bar1 = 5;
sarr(2).foo.bar2 = 5;
sarr(2).dings = 2;
% apply mean to all nested fields:
sarr_mean = nestedSarrFun(#mean, sarr);
Example Result:
sarr_mean.foo.bar1 = 3.5
sarr_mean.foo.bar2 = 6
sarr_mean.dings = 1.5
In Matlab2017 (I am not sure about older versions), an array of structs can return an array of the field of its structs like so:
struct1.x = 1;
struct2.x = 2;
% array of 2 structs:
struct_array = [struct1, struct2];
% array of field x of each struct:
[struct_array.x]
which returns
ans =
1 2
In your case, the data is not in a field of your struct, but in a subfield output_metric_a. Therefore, you first need to this twice:
trial1.output_metric_a.value_1 = 1;
trial2.output_metric_a.value_1 = 2;
trials = [trial1, trial2];
output_metric_a_array = [trials.output_metric_a];
value_1_array = [output_metric_a_array.value_1];
mean_of_value_1 = mean(value_1_array)
which returns
mean_of_value_1 =
1.5000
I tried below code but it ultimately prints 5 zeros after giving the user defined values to array .
the below code takes array of size 5 and gives user defined values
object printarray {
def main(args:Array[String]) {
val arr = new Array[Int](5)
println("the values of array is ")
for(i<-0 to 4) {
val arr = scala.io.StdIn.readInt()
}
arr.foreach(println)
}
}
There are a couple of things that need improvement in the code.
You allocate an array of 5 elements named arr in the scope of the main method, but you also declare an additional value with the same name, arr, inside the for comprehension scope and read an Int into it, which you discard once you exit the for scope. Then, you print the array in the outer scope, which hasn't changed at all.
The first thing you need to make this work, is index into the array instead of creating a new value named arr in the inner scope:
object printarray {
def main(args:Array[String]) {
val arr = new Array[Int](5)
println("the values of array is ")
for (i <- 0 to 4) {
arr(i) = scala.io.StdIn.readInt()
}
arr.foreach(println)
}
}
To improve things further, you use the yield Scala synax to make this more concise:
val arr = for (i <- 0 to 4) yield StdIn.readInt()
This will not return an Array[Int], but an IndexedSeq[Int] with an underlying type of Vector[Int]. If you still want an Array[Int], you'll have to explicitly call toArray:
val arr: Array[Int] = (for (i <- 0 to 4) yield scala.io.StdIn.readInt()).toArray
In your for-loop you are reassigning the variable in every iteration. You can change it to:
for(i <- 0 to 4) {
arr(i) = scala.io.StdIn.readInt()
}
As a side-note, instead of declaring the arr before the loop you can simply do:
val arr = for(i <- 0 to 4) yield scala.io.StdIn.readInt()
I want to get a value from a structure array by code, and I'll have the index stored in a string.
I've tried to run this code:
function M = getdata(matrix,field,varargin)
exp = [];
for i = 1:nargin-3
exp = [exp num2str(varargin{i}) ','];
end
exp = [exp num2str(varargin{nargin-2})];
M = eval('matrix(exp).(Field)');
end
However, it fails.
For example, suppose I have a structure array with 2 fields, A and B. So, I could write
MyStruct(1,1).A
A possible use would be:
M = getdata(MyStruct,A,1,1)
and I want the program to do:
M = MyStruct(1,1).A
How could I do that?
Thanks!
You can use the getfield function:
M = getfield(MyStruct, {1,1} ,'A');
Or if you wanted, say, MyStruct(1,1).A(3).B:
M = getfield(MyStruct, {1,1}, 'A', {3},'B');
For the example you give, this will suffice:
function M = getdata(matrix,field,varargin)
M = matrix(varargin{:}).(field);
which you call like
getdata(myStruct, 'A', 1,1)
which makes that function pretty useless.
But, in general, when you have indices given as strings, you can follow roughly the same approach:
%// Your indices
str = {'1', '2'};
%// convert to numbers
str = cellfun(#str2double, str, 'UniformOutput', false);
%// use them as indices into structure
M = myStruct(str{:}).(field)
And if you really insist, your call to eval is just wrong:
M = eval(['matrix(' exp ').(' field ')']);
And, as a general remark, please refrain from using exp as the name of a variable; it is also the name of a built-in function (the natural exponential function).