Concatenating an array of arrays in Coffeescript - arrays

I'm trying to find an elegant way in Coffeescript to merge an array of arrays, so that [[1,2,3],[4,5,6],[7,8,9]] ==> [1,2,3,4,5,6,7,8,9].
As you might imagine, I need this because I'm generating arrays from a function in a "for in" construct and need to concatenate the resulting nested array:
result = (generate_array(x) for x in arr)
Is there an elegant way to handle this? Thanks for any pointers!

Just use the JS idiom:
[].concat.apply([], a)
which becomes a little nicer in Coffee:
$ coffee -e 'a = [[1,2,3],[4,5,6],[7,8,9]]; console.dir [].concat a...'
[ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

OK, one way is to include the underscore.js library. It is a very nice, lightweight but powerful utility library, and it has _.flatten which does exactly this.
Barring that, you could take the underscore.js code for flatten and modify it to remove any other underscore dependencies to create your own standalone "flatten".
Here's the underscore.js "_.flatten" code:
_.flatten = function(array) {
return _.reduce(array, function(memo, value) {
if (_.isArray(value)) return memo.concat(_.flatten(value));
memo[memo.length] = value;
return memo;
}, []);
};
Notice that it is doing some nice stuff for you. For example, many of the underscore functions like _.reduce will check to see if the browser has implemented a native version, which some have. If so, it will use the native which of course runs much faster. The _.isArray implementation does the same thing.

What about this for Coffee
[[1, 2, 3], [4, 5, 6], [7, 8, 9]].reduce (a, b) ->
a.concat b
or this for pure Javascript
[[1, 2, 3], [4, 5, 6], [7 , 8, 9]].reduce((a, b) => a.concat(b));

sugarjs is another elegance way to do it:
[[1, 2, 3]].flatten() //=> [1, 2, 3]
sugarjs: flatten

Why not try using Lodash?
_.flatten([1,2,3], [4,5,6]) => [1,2,3,4,5,6]
https://lodash.com/docs#flatten

Related

Does ruby support an enumerable map_cons method or its equivalent?

Ruby has a handy function for enumerables called each_cons. Which "Iterates the given block for each array of consecutive elements." This is really nice. Except that this is definitely an each method, which returns nil upon completion and not an array of the values you've looped over like map would.
However, if I have a situation where I need to iterate over an enumerable type, take an element and its cons, then perform some operation on them and return them back into an array what can I do? Normally, I'd use map for this sort of behavior. But map_cons doesn't exist.
An example:
Given a list of integers, I need to see which ones of those integers repeat and return a list of just those integers
[1, 1, 4, 5, 6, 2, 2] ## I need some function that will get me [1, 2]
I can say:
[1, 1, 4, 5, 6, 2, 2].each_cons(2) {|e| e[0] if e[0] == e[1]}
But, since it eachs over the array, it will complete successfully and return nil at the end. I need it to behave like map and not like each.
Is this behavior something that ruby supports? Am I coming at it from the wrong direction entirely?
The documentation of each_cons ends with this innocent phrase: "If no block is given, returns an enumerator." Most methods of Enumerable do this. What can you do with an Enumerator? Nothing truly impressive . But Enumerators include Enumerable, which does provide a large amount of powerful methods, map being one of them. So, as Stefan Pochmann does:
[1, 1, 4, 5, 6, 2, 2].each_cons(2).map { |e| e[0] if e[0] == e[1] }
each_consis called without a block, so it returns an Enumerator. mapis simply one of its methods.
Just add map?
[1, 1, 4, 5, 6, 2, 2].each_cons(2).map { |e| e[0] if e[0] == e[1] }
=> [1, nil, nil, nil, nil, 2]
Ruby 2.7 added the method filter_map which makes this even easier:
p [1, 1, 4, 5, 6, 2, 2].each_cons(2).filter_map{|a,b| a if a == b} # => [1, 2]

How to reference the array push is being called upon?

I'm trying to create an array, where the first element and the last element are the same. I would like to be able to do so without having to assign the array a name. Consider the following code:
[1, 2, 3, 4].push(self[0])
Obviously, this use of self is in error because self refers to the main object. And so, my question:
When I call .push, in its parameters how do I refer to the array push is being called upon?
Well, one option is to use instance_eval to make self refer to the object you are working with:
[1, 2, 3, 4].instance_eval { self.push(self[0]) }
# => [1, 2, 3, 4, 1]
One way to do this without changing the context of self is to use Object#tap - which will yield the object to a block, and then return the (new) value of the object:
[1, 2, 3, 4].tap { |a| a << a[0] }
#=> [1, 2, 3, 4, 1]
# Or equivalently:
[1, 2, 3, 4].tap { |a| a.push(a[0]) }
Another alternative (which generally would not be recommended, especially in a large project, as it pollutes the core classes; but could be a viable choice in a small script) would be to define a method in the Array class itself:
class Array
def push_first
push(first)
end
end
[1, 2, 3, 4].push_first
#=> [1, 2, 3, 4, 1]

Swift create one Int array from two int arrays by taking the max() at each index

I feel like this may call for reduce, map or something like it to solve but I'm not yet familiar enough with these and was hoping someone here might be. Lets say I have
arrayOne = [1, 3, 7]
arrayTwo = [2, 1, 10]
the expected result for what I'm trying to do would be
mergedArray = [2, 3, 10]
I know I can do this with a relatively simple for loop in a method but I am looking for a more "swift" way to do it if it's possible.
And Yes, both arrays will always be the same length.
This will work:
let arrayOne = [1, 3, 7]
let arrayTwo = [2, 1, 10]
let mergedArray = zip(arrayOne, arrayTwo).map{max($0, $1)}
First, pair each element in two arrays with zip, and then use map to each pair.

Difference between two arrays in Angular JS

Consider following arrays:
array1 = ['a','b'];
array2 = ['a','b','c','d'];
I need to extract the difference. So my resulting array should look something like,
array3 = ['c','d'];
If an element is present in array1 then it should be poped from array2.
I am looking for solutions more angular way,is there any directive available?
In my opinion you can use underscore or lodash library for such tasks.
for example in underscore you can done it through this simple code :
difference_.difference(array, *others)
Similar to without, but returns the values from array that are not present in the other arrays.
_.difference([1, 2, 3, 4, 5], [5, 2, 10]);
=> [1, 3, 4]
underscore annotated source

Flatten all values of multiple arrays in Swift

I have a Dictionary of Integer Arrays like below:
let numbers = [1: [2, 3], 4: [5, 6, 7], 8: [9]]
What I really want is a single flattened Array of all of the values (which themselves are arrays), like so:
[2, 3, 5, 6, 7, 9]
Now, I have been able to call numbers.values.array to get:
[[2, 3], [5, 6, 7], [9]]
But what I'm looking for is to merge these one step further, flattening them.
Does Swift (1.1, or 1.2) offer a convenience method for this?
With a combination of numbers.values.array and a reduce function you can simplify this down in one line of code.
numbers.values.array.reduce([], combine: +) // [5,6,7,2,3,9]
However, I would like to note that since you are using a dictionary, you cannot guarantee that the values will be sorted, so you can use the sorted function to accomplish this:
sorted(numbers.values.array.reduce([], combine: +), <) // [2,3,5,6,7,9]
As #Jeffery Thomas stated, you can also use flatmap which was just added in Swift 1.2:
sorted(numbers.values.array.flatMap { $0 }, <)
And to take it a step further, using the global sorted function, the < is extraneous because it is the default and using the global reduce and flatMap functions, you can remove the array property as pointed out by Martin R, so it can be reduced down to:
sorted(reduce(numbers.values, [], +))
sorted(flatMap(numbers.values) { $0 })
Another possible solution is
[].join(numbers.values)
And if you want the values in the order corresponding to the sorted
dictionary keys then it would be
flatMap(sorted(numbers.keys)) { numbers[$0]! }
This is called flattening, and it's a relatively common operation. There are a number of ways to do it, so pick one that suits your needs.
numbers.values.array.reduce([], combine: +) // As stated by #Bluehound
reduce(numbers.values, [], +)
numbers.values.array.flatMap { $0 } // Swift 1.2 (Xcode 6.3)
flatMap(numbers.values) { $0 } // Swift 1.2 (Xcode 6.3)
flatMap may be the most useful, if the next step after flattening is mapping.
NOTE: Thanks #MartinR for the syntax tip.

Resources