Getting the first and last element of an array in CoffeeScript - arrays

If say I have an array and I would to iterate through the array, but do something different to the first and last element. How should I do that?
Taking the below code as example, how do I alert element a and e?
array = [a,b,c,d,e]
for element in array
console.log(element)
Thanks.

You can retrieve the first and last elements by using array destructuring with a splat:
[first, ..., last] = array
This splat usage is supported in CoffeeScript >= 1.7.0.

The vanilla way of accessing the first and last element of an array is the same as in JS really: using the index 0 and length - 1:
console.log array[0], array[array.length - 1]
CoffeeScript lets you write some nice array destructuring expressions:
[first, mid..., last] = array
console.log first, last
But i don't think it's worth it if you're not going to use the middle elements.
Underscore.js has some helper first and last methods that can make this more English-like (i don't want to use the phrase "self-explanatory" as i think any programmer would understand array indexing). They are easy to add to the Array objects if you don't want to use Underscore and you don't mind polluting the global namespace (this is what other libraries, like Sugar.js, do):
Array::first ?= (n) ->
if n? then #[0...(Math.max 0, n)] else #[0]
Array::last ?= (n) ->
if n? then #[(Math.max #length - n, 0)...] else #[#length - 1]
console.log array.first(), array.last()
Update
This functions also allow you to get the n first or last elements in an array. If you don't need that functionality then the implementation would be much simpler (just the else branch basically).
Update 2
CoffeeScript >= 1.7 lets you write:
[first, ..., last] = array
without generating an unnecessary array with the middle elements :D

The shortest way is here
array[-1..]
See this thread
https://github.com/jashkenas/coffee-script/issues/156

You can use just:
[..., last] = array

You can use slice to get last element. In javascript, slice can pass negative number like -1 as arguments.
For example:
array = [1, 2, 3 ]
console.log "first: #{array[0]}"
console.log "last: #{array[-1..][0]}"
be compiled into
var array;
array = [1, 2, 3];
console.log("first: " + array[0]);
console.log("last: " + array.slice(-1)[0]);

You can get the element and the index of the current element when iterating through the array using Coffeescript's for...in. See the following code, replace the special_process_for_element and normal_process_for_element with your code.
array = [a, b, c, d]
FIRST_INDEX = 0
LAST_INDEX = array.length - 1
for element, index in array
switch index
when FIRST_INDEX, LAST_INDEX
special_process_for_element
else
normal_process_for_element
sample
Here's a working code

Related

How to merge 2 arrays of equal length into a single dictionary with key:value pairs in Godot?

I have been trying to randomize the values in an ordered array (ex:[0,1,2,3]) in Godot. There is supposed to be a shuffle() method for arrays, but it seems to be broken and always returns "null". I have found a workaround that uses a Fisher-Yates shuffle, but the resulting array is considered "unsorted" by the engine, and therefore when I try to use methods such as bsearch() to find a value by it's position, the results are unreliable at best.
My solution was to create a dictionary, comprised of an array containing the random values I have obtained, merged with a second array of equal length with (sorted) numbers (in numerical order) which I can then use as keys to access specific array positions when needed.
Question made simple...
In GDScript, how would you take 2 arrays..
ex: ARRAY1 = [0,1,2,3]
ARRAY2 = [a,b,c,d]
..and merge them to form a dictionary that looks like this:
MergedDictionary = {0:a, 1:b, 2:c, 3:d}
Any help would be greatly appreciated.
Godot does not support "zip" methodology for merging arrays such as Python does, so I am stuck merging them manually. However... there is little to no documentation about how to do this in GDScript, despite my many hours of searching.
Try this:
var a = [1, 2, 3]
var b = ["a", "b", "c"]
var c = {}
if a.size() == b.size():
var i = 0
for element in a:
c[element] = b[i]
i += 1
print("Dictionary c: ", c)
If you want to add elements to a dictionary, you can assign values to the keys like existing keys.

Why does Ruby's each_with_object drop data that was appended with the += operator to the array memo?

I'm stumped by the following Ruby behaviour:
result = [1,2,3].each_with_object([]) do |elem, memo|
memo << [elem]
end
puts result.to_s
# => [[1], [2], [3]]
The above code works how I would expect it to work. However, the code below just seems to drop the numbers I'm trying to append to the array.
result = [1,2,3].each_with_object([]) do |elem, memo|
memo += [elem]
end
puts result.to_s
# => []
Could anyone explain to me what's going on here and how I am supposed to use the += operator with each_with_object in the above context?
memo is local variable, that points to an array object. these loop variables are set at each iteration.
In the first example, you change this array object.
In the second example, you override the local variable with a new array. Because memo += [elem] is just a shorthand for memo = momo + [elem]
The old array stays empty.
Very often you better use inject instead of each_with_object. With inject, the new memo variable is set with the result of the block, so you can use non-destructive functions.
[1,2,3].inject([]) do |memo, elem|
memo + [elem]
end
According to docs, += – concatenation – returns a new array built by concatenating the two arrays together to produce a third array.
Thus, on every iteration the block result is set to a new array, that is reset back to the empty array that you've passed to each_with_object method in the next iteration. Consider the following demonstration.

Ruby: `each': stack level too deep (SystemStackError) sorting array algorithm

I'm trying to build sorting method in Ruby to sort number in array. This is an example exercise from the book.
The program will look at each element in the original array, and determine the lowest value of them all.
Then it add that value to a newly created array called "sorted", and remove that number from the original array.
We now have the original array losing 1 element and the new array having 1 element. We repeat the above steps with these adjusted arrays until the original one turns empty.
However, I have got the error that I can't understand what's happening:
Blockquote./sorting_argorith.rb:9:in `each': stack level too deep (SystemStackError)
This is my code:
array = [6,4,8,3,2,4,6,7,9,0,1,8,5]
def sorta array #method wrapper
really_sort array, []
end
def really_sort array, sorted #main method
a = array[0] # set a = the first element
array.each do |i|
if a > i
a = i #check each element, if anything small than a,
end # set a to that value
end
sorted.push a #we've got the smallest element as a,
array.delete a #it is then moved from the old to the new array
if array == []
break
end
really_sort array, sorted #keep going with my two modified arrays
end # till the original is empty (completely moved)
sorta array #call the wraped method
puts
print array
print sorted
use return sorted instead of break because you are inside method not inside loop
so use this
array = [6,4,8,3,2,4,6,7,9,0,1,8,5]
def sorta(array) #method wrapper
really_sort(array, [])
end
def really_sort(array, sorted) #main method
a = array[0] # set a = the first element
array.each do |i|
if a > i
a = i #check each element, if anything small than a,
end # set a to that value
end
sorted.push(a) #we've got the smallest element as a,
array.delete(a) #it is then moved from the old to the new array
if array == []
return sorted
end
really_sort(array, sorted) #keep going with my two modified arrays
end
sorted = sorta(array)
p sorted
# => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
BTW: Better use array.empty? instead of array == []
There might be a problem with the proposed solution(s) -- the Array#delete method will remove all occurrences of the object you provide as a parameter. Consider the first iteration through the loop; when you call array.delete(a) with the value of 6 it will remove two sixes from the original array (indexes 0, 6).
Here's an alternative that preserves all the original elements.
array = [6,4,8,3,2,4,6,7,9,0,1,8,5]
sorted = []
until array.empty?
min = array.min
idx = array.index(min)
sorted.push(array.delete_at(idx))
end
Array#min will return the smallest value from the array
Array#index will return the index of the first occurrence of the object
Array#delete_at will remove the object at the specified index (and return it)

Efficient method of merging two neighboring indicies in Scala

What would be a most efficient method of merging two neighboring indicies in Scala? What I have in mind a nasty while loops with copying.
For example, there's a buffer array A, with length N. The new array need be generated such that for A(i) = A(i) + A(i+1), where i < N
For example, merging and summing the second and third element, and generate a new array.
ArrayBuffer(1,2,4,3) => ArrayBuffer(1,6,3)
UPDATE:
I think I come up with some solution, but doesn't like it much. Any suggestion to improve would be highly appreciated.
scala> val i = 1
i: Int = 1
scala> ArrayBuffer(1,2,4,3).zipWithIndex.foldLeft(ArrayBuffer[Int]())( (k,v)=> if(v._2==i+1){ k(k.length-1) =(k.last+v._1);k; }else k+= v._1 )
The simplest way to get neighbors is to use sliding method.
a.sliding(2, 1).map(_.sum)
where the first argument is a size and the second one is step.
If you want to keep the first and the last element intact something like this should work:
a.head +: a.drop(1).dropRight(1).sliding(2, 1).map(_.sum).toArray :+ a.last
If you want to avoid copying and array on append/prepend you can rewrite it as follows:
val aa = a.sliding(2, 1).map(_.sum).toArray
aa(0) = a.head
aa(aa.size - 1) = a
or use ListBuffer which provides constant time prepend and append.
It should be also possible to use Iterators:
val middle: Iterator[Int] = a.drop(1).dropRight(1).sliding(2, 1).map(_.sum)
(Iterator(a.head) ++ middle ++ Iterator(a.last)).toArray // or toBuffer

Modify hashes in an array based on another array

I have two arrays like this:
a = [{'one'=>1, 'two'=>2},{'uno'=>1, 'dos'=>2}]
b = ['english', 'spanish']
I need to add a key-value pair to each hash in a to get this:
a = [{'one'=>1, 'two'=>2, 'language'=>'english'},{'uno'=>1, 'dos'=>2, 'language'=>'spanish'}]
I attempted this:
(0..a.length).each {|c| a[c]['language']=b[c]}
and it does not work. With this:
a[1]['language']=b[1]
(0..a.length).each {|c| puts c}
an error is shown:
NoMethodError (undefined method '[]=' for nil:NilClass)
How can I fix this?
a.zip(b){|h, v| h["language"] = v}
a # => [
# {"one"=>1, "two"=>2, "language"=>"english"},
# {"uno"=>1, "dos"=>2, "language"=>"spanish"}
# ]
When the each iterator over your Range reaches the last element (i.e. a.length), you will attempt to access a nonexisting element of a.
In your example, a.length is 2, so on the last iteration of your each, you will attempt to access a[2], which doesn't exist. (a only contains 2 elements wich indices 0 and 1.) a[2] evaluates to nil, so you will now attempt to call nil['language']=b[2], which is syntactic sugar for nil.[]=('language', b[2]), and since nil doesn't have a []= method, you get a NoMethodError.
The immediate fix is to not iterate off the end of a, by using an exclusive Range:
(0...a.length).each {|c| a[c]['language'] = b[c] }
By the way, the code you posted:
(0..a.length).each {|c| puts c }
should clearly have shown you that you iterate till 2 instead of 1.
That's only the immediate fix, however. The real fix is to simply never iterate over a datastructure manually. That's what iterators are for.
Something like this, where Ruby will keep track of the index for you:
a.each_with_index do |hsh, i| hsh['language'] = b[i] end
Or, without fiddling with indices at all:
a.zip(b.zip(['language'].cycle).map(&:reverse).map(&Array.method(:[])).map(&:to_h)).map {|x, y| x.merge!(y) }
[Note: this last one doesn't mutate the original Arrays and Hashes unlike the other ones.]
The problem you're having is that your (0..a.length) is inclusive. a.length = 2 so you want to modify it to be 0...a.length which is exclusive.
On a side note, you could use Array#each_with_index like this so you don't have to worry about the length and so on.
a.each_with_index do |hash, index|
hash['language'] = b[index]
end
Here is another method you could use
b.each_with_index.with_object(a) do |(lang,i),obj|
obj[i]["language"] = lang
obj
end
#=>[
{"one"=>1, "two"=>2, "language"=>"english"},
{"uno"=>1, "dos"=>2, "language"=>"spanish"}
]
What this does is creates an Enumerator for b with [element,index] then it calls with_object using a as the object. It then iterates over the Enumerator passing in each language and its index along with the a object. It then uses the index from b to find the proper index in a and adds a language key to the hash that is equal to the language.
Please know this is a destructive method where the objects in a will mutate during the process. You could make it non destructive using with_object(a.map(&:dup)) this will dup the hashes in a and the originals will remain untouched.
All that being said I think YAML would be better suited for a task like this but I am not sure what your constraints are. As an example:
yml = <<YML
-
one: 1
two: 2
language: "english"
-
uno: 1
dos: 2
language: "spanish"
YML
require 'yaml'
YAML.load(yml)
#=>[
{"one"=>1, "two"=>2, "language"=>"english"},
{"uno"=>1, "dos"=>2, "language"=>"spanish"}
]
Although using YAML I would change the structure for numbers to be more like language => Array of numbers by index e.g. {"english" => ["zero","one","two"]}. That way you can can access them like ["english"][0] #=> "zero"

Resources