can the keyword "foreach" get the array parameter? - arrays

I am a beginner of the scala. many concepts aren't clear for me.
I want to ask that if the foreach can get (or control) the array parameter ?
for example:
val array = Array.ofDim[Double](2,6)
I can use for to control the array's parameter, like
for( i <- 0 until 2){
for(j <- 0 until 6){
......... }}
I can use i,j control and get the parameter. Is "foreach" can do that??
(I know foreach can do things without the parameter, but I just want to ask if it can get
the array parameter?)
thank you :)

I'm not exactly sure what you're asking. If you're asking how to loop over the full array item-by-item, then you can do that without nesting for comprehensions. This will print the contents of your 2D array:
for (row <- array; col <- row) println(col)
If you're asking how to loop over all the indices of the array (I think maybe that's what you mean when you say parameter), then you can use the indices property:
for (i <- array.indices; j <- array(i).indices) println(array(i)(j))
If you're just trying to do indexOf across a 2D array, you can probably just reuse the solution for indexOf for 2D Vector in Scala. This is how I'd adapt it to your code:
val array = Array.tabulate(2,6)(_*6+_)
val searchValue = 8
val indices: Option[(Int, Int)] =
(for {
i <- array.indices
j <- array(i).indices
if (array(i)(j) == searchValue)
} yield (i, j)).headOption
If none of the values match, you'll get indices = None. In this case there is a match, so you get indices = Some((1,2)), because 8 is at array(1)(2).
(Note: Unlike indexOf, using a for comprehension does not short-circuit as soon as it finds the solution. If you make the index ranges lazy by calling .iterator, .view or .toStream then you'll get the expected short-circuiting behavior.)

U can use the function [ indexOf(elem: T): Int ] that will return the position
Scala Array

Related

OCaml matching in a sorting algorithm 0(n^2)

I have tried several things. Can I simply not match with less than?
The exception is redundant, to enable the matching loop. I can imagine all sorts of things are wrong and this bit of code. It would be nice if the vague less-than-you-less-than-me concept worked.
I admit I am frustrated. Why do I get an error at j < k every time, no matter where I improve or edit? Is that simply against the rules?
I was just looking at Array Length > Array Length as my while condition, that will have to change. Also, none of the Array Sorting methods seem to me to work in the smallest upwards routine as I understand the 0(n^2).
Can this code implement Array.for_all as a sorting algorithm?
UPDATE
let i = Array.length arr in
let sort (arr : array) (j : int) (k : int) =
Array.make n x = unsorted(arr : array) (n : int) (x : int)
while i > 0
match j < k with
| true -> a.(n) <- j
| false -> failwith (Printf.sprintf "Exception Found (%d)" i)
i - 1
;;
That was a lot of questions.
Thank you.
UPDATE:
I appreciate the help very much.
I know I need two arrays, not one. The finished code should read an array, and then give an array back. So, when k points to a smallest j the purpose of the algorithm is to kick j out of the first array, from wherever it it is, put it into the second array, and append every j after that one into the second array. The job is done when the first array is empty.
I see plenty of information about lists out there but not much about arrays. How can I remove the j_n-th element of an array?
This is a nice looking example of recursion used to search and delete an element from a list, can that work in an array?
Thank you again
The match in OCaml is restricted (in essence) to matching a value (an expression) against a set of structured constants that are known at compile time. If you want to test something like whether j < k you should just use an if expression, even if it's not as exotic and powerful seeming.
There are many other problems with your code, but this seems to answer your main question.
You can use an expression in a when clause to further constrain when a pattern matches. Simple example:
let f x =
match x with
| _ when x < 5 -> true
| _ -> false
In this trivial case, an if is of course better, but it can be useful in more complicated pattern matching with lots of options.
You'll have a lot of problems with your code but to answer your question, there are 3 ways I can see to do what you want to do:
match j < k with
| true -> a.(n) <- j
| false -> failwith (Printf.sprintf "Exception Found (%d)" i)
match j with
| _ when j < k -> a.(n) <- j
| _ -> failwith (Printf.sprintf "Exception Found (%d)" i)
if j < k
then a.(n) <- j
else failwith (Printf.sprintf "Exception Found (%d)" i)
The latter being the better. The only thing you need to remember is that pattern matching is done on patterns, it looks at what the values are, not their relations to other values. You can match an int with 1, 3 or 127 but not match this int with another one or compare it with another one.
On a side note, here are some problems in your code and some answers to your questions:
sort takes an array, a j, a k and a i but then
You use Array.make by checking if it's equal to unsorted (x = f is a boolean comparison unless you write let x = f in ...). It looks like you're trying to define an internal function but it's unclear how you're making it
if you want to define a randomly sorted array, you could just write Array.init 100 (fun _ -> Random.int 100)
you're clearly trying to sort your array between i and n (while a.(i) > a.(n) do ... done but then you're checking on j that is a parameter of your function and that never changes
Array.for_all checks that a predicate is true for every value in the array. If you want to apply a function with a different return type to your array you can either use Array.map:
map f a applies function f to all the elements of a, and builds an array with the results returned by f: [| f a.(0); f a.(1); ...; f a.(length a - 1) |].
or Array.fold_{left|right}:
fold_left f init a computes f (... (f (f init a.(0)) a.(1)) ...) a.(n-1), where n is the length of the array a.
fold_right f a init computes f a.(0) (f a.(1) ( ... (f a.(n-1) init) ...)), where n is the length of the array a.
As for the sorting functions, what makes you think they won't run in O(n^2)? You can look at the way they're implemented here

Is there a way to split an array into a multidimensional array with a conditional?

I am trying to "Implement a first method size_splitter which takes two parameters: an array, and a integer (the size). We will assume that the array only contains words, e.g. Strings, and that the arbitrary rule is to form two groups: the first one with words of the given size (second parameter of the method), and the other group with all the other words.
The size_splitter method should return an array of two arrays - the two groups defined above - with the contents sorted alphabetically."
I can so far return the size of the array, but any sort of sorting doesnt work right.
I have tried to create 2 empty arrays and all words in the main array that == the target size go into array1 and others into array2. then i push arrays 1 and 2 into the main array.
after that i want to return the arrays both sorted, but i am not quite far enought to worry about that.
def size_splitter(array, size)
# TODO: Return an array of two arrays, the first containing
# words of length `size`, the second containing all the other words
# In addition to this split, each array should be *sorted*
ary1 = []
ary2 = []
array.map do |word|
word.length == size ? ary1.push(word) : ary2.push(word)
array.push(ary1, ary2)
return array.sort!
end
end
I expect to at least be able to first sort the elements by size, but that seems to be where the first problems start.
I would use partition to split the array and that just sort the subarrays:
def size_splitter(array, size)
array.partition { |string| string.size == size }.map(&:sort)
end
It seems that sorting the array first might be a relatively simple approach.
I don't think that there's a single correct way to implement this, but here's an alternative that adds the values to a hash's values based on whether they match the size condition or not, and then reads the resulting values.
def size_splitter(array, size)
array.sort.each_with_object({true => [], false => []}) do |string, hash|
hash[string.size == size] << string
end.values
end
This is also quite readable:
def size_splitter(array, size)
[
array.select{|string| string.size == size}.sort,
array.reject{|string| string.size == size}.sort
]
end
While I consider #spickermann answer the best approach, I'd suggest a fix for you method.
Move the return outside the map loop, but use each instead, since you defined empty arrays to collect the elements. Then return the two sorted arrays:
def size_splitter(array, size)
ary1 = []
ary2 = []
array.each do |word|
word.length == size ? ary1.push(word) : ary2.push(word)
end
return [ary1.sort, ary2.sort]
end
ary = %w|Tom Bob Greg Sam Sonny Thomas|
size_splitter(ary, 3)
#=> [["Bob", "Sam", "Tom"], ["Greg", "Sonny", "Thomas"]]
I see you calling array.sort. On first glance I would be under the impression that this attempts a sort on the parent array that contains the arrays you are actually interested in sorting.
Perhaps try
array.push(ary1.sort, ary2.sort)
return array

Why does this simple array access not work in Swift?

var word = "morning"
var arr = Array(word)
for s in 0...word.count {
print(arr[s])
}
This will not print. Of course, if I substitute a number for s, the code works fine.
Why will it not accept a variable in the array access braces? Is this peculiar to Swift?
I've spent a long time trying to figure this out, and it's nothing to do with s being optional.
Anyone understand this?
you are using inclusive range ... instead of ..<, so s goes from 0 to 7, not 0 to 6.
However, in arr the index goes from 0 to 6 because there are 7 characters.
Thus, when the program tries to access arr[7], it throws an index out of range error.
If you were coding on Xcode, the debugger would have told you that there is no arr[7].
As for the code, here is a better way to print every item in arr than using an index counter:
var word = "morning"
var arr = Array(word)
for s in arr {
print(s)
}
This is called a "foreach loop", for each item in arr, it assigns it to s, performs the code in the loop, and moves on to the next item, assigns it to s, and so on.
When you have to access every element in an array or a collection, foreach loop is generally considered to be a more elegant way to do so, unless you need to store the index of a certain item during the loop, in which case the only option is the range-based for loop (which you are using).
Happy coding!
When I run it, it prints the array then throws the error Fatal error: Index out of range. To fix this, change the for loop to:
for s in 0..<word.count {
print(arr[s])
}
try this
when you use a word to recognize
size of Array your Array index start as 0 so array last index must be equal with your (word.count - 1)
var word = "morning"
var arr = Array(word)
for s in 0...(word.count-1) {
print(arr[s])
}
Basically avoid index based for loops as much as possible.
To print each character of a string simply use
var word = "morning"
for s in word { // in Swift 3 word.characters
print(s)
}
To solve the index issue you have to use the half-open range operator ..< since indexes are zero-based.

Subtracting from each element in array in python

I've got a sort of array in python, and i'm looking to subtract one from each int in all of it. for example:
arr = [[2,3,4],
[5,6,7],
[8,9,10]]
#this should become this:
arr = [[1,2,3],
[4,5,6],
[7,8,9]]
there's a few ways i've tried to do this
for i in arr:
for j in i:
j-=1 #doesn't work!
I'm aware it would be easier to do this with numpy, but this is for a large project that i'm working on, so implementing numpy would take hours, if not more. Thanks!
So the way that you are doing it is just reassigning the variable j within your loop to one less its original value. However, what you want to do is reassign the value of the array AT the index j to one less its original value. To do this without using numpy, simply loop through all the indexes of the array, and then replace the value:
for i in range(len(arr)):
for j in range(len(arr[i])):
arr[i][j] -= 1
If you're unsure of why this is, look into how variable assignment works in Python.
You could use a nested list comprehension:
arr = [[y - 1 for y in x] for x in arr]
Your solution didn't work, because jis a copy of the value from your array, rather than a pointer to the array item itself.
Below is sample code that works. Essentially, iterate through each location in the array, and modify the original array at that location.
arr = [[2,3,4],
[5,6,7],
[8,9,10]]
for x_idx, x in enumerate(arr):
for y_idx, y in enumerate(x):
arr[x_idx][y_idx] -= 1
print(arr)

Is there an idiomatic way to exchange two elements in a cell array?

I know that I can write it like this:
tmp = arr{i}
arr{i} = arr{j}
arr{j} = tmp
But is there a simpler way? For instance, in Python I'd write:
arr[i], arr[j] = arr[j], arr[i]
Standard, idiomatic way:
Use a vector of indices:
arr([i j]) = arr([j i]); %// arr can be any array type
This works whether arr is a cell array, a numerical array or a string (char array).
Not recommended (but possible):
If you want to use a syntax more similar to that in Python (with a list of elements instead of a vector of indices), you need the deal function. But the resulting statement is more complicated, and varies depending on whether arr is a cell array or a standard array. So it's not recommended (for exchanging two elements). I include it only for completeness:
[arr{i}, arr{j}] = deal(arr{j}, arr{i}); %// for a cell array
[arr(i), arr(j)] = deal(arr(j), arr(i)); %// for a numeric or char array
Not to confuse things, but let me another syntax:
[arr{[i,j]}] = arr{[j,i]};
or
[arr{i},arr{j}] = arr{[j,i]};
The idea here is to use comma-separated lists with curly-braces indexing.
Remember that when working with cell-arrays, ()-indexing gives you a sliced cell-array, while {}-indexing extracts elements from the cell-array and the return type is whatever was stored in the specified cell (when the index is non-scalar, MATLAB returns each cell content individually as a comma-separated list).

Resources