How to Pass an Argument to Array.Map Short Cut

How do I pass an argument to array.map short cut?

You can't do it like this. The & operator is for turning symbols into procs.

a = [1, 2, 3, 4, 5]  
puts a.map(&:to_s) # prints array of strings
puts a.map(&:to_s2) # error, no such method `to_s2`.

& is a shorthand for to_proc:

def to_proc
proc { |obj, *args| obj.send(self, *args) }
end

It creates and returns new proc. As you see, you can't pass any parameters to this method. You can only call the generated proc.

Can you supply arguments to the map(&:method) syntax in Ruby?

You can create a simple patch on Symbol like this:

class Symbol
def with(*args, &block)
->(caller, *rest) { caller.send(self, *rest, *args, &block) }
end
end

Which will enable you to do not only this:

a = [1,3,5,7,9]
a.map(&:+.with(2))
# => [3, 5, 7, 9, 11]

But also a lot of other cool stuff, like passing multiple parameters:

arr = ["abc", "babc", "great", "fruit"]
arr.map(&:center.with(20, '*'))
# => ["********abc*********", "********babc********", "*******great********", "*******fruit********"]
arr.map(&:[].with(1, 3))
# => ["bc", "abc", "rea", "rui"]
arr.map(&:[].with(/a(.*)/))
# => ["abc", "abc", "at", nil]
arr.map(&:[].with(/a(.*)/, 1))
# => ["bc", "bc", "t", nil]

And even work with inject, which passes two arguments to the block:

%w(abecd ab cd).inject(&:gsub.with('cde'))
# => "cdeeecde"

Or something super cool as passing [shorthand] blocks to the shorthand block:

[['0', '1'], ['2', '3']].map(&:map.with(&:to_i))
# => [[0, 1], [2, 3]]
[%w(a b), %w(c d)].map(&:inject.with(&:+))
# => ["ab", "cd"]
[(1..5), (6..10)].map(&:map.with(&:*.with(2)))
# => [[2, 4, 6, 8, 10], [12, 14, 16, 18, 20]]

Here is a conversation I had with @ArupRakshit explaining it further:

Can you supply arguments to the map(&:method) syntax in Ruby?


As @amcaplan suggested in the comment below, you could create a shorter syntax, if you rename the with method to call. In this case, ruby has a built in shortcut for this special method .().

So you could use the above like this:

class Symbol
def call(*args, &block)
->(caller, *rest) { caller.send(self, *rest, *args, &block) }
end
end

a = [1,3,5,7,9]
a.map(&:+.(2))
# => [3, 5, 7, 9, 11]

[(1..5), (6..10)].map(&:map.(&:*.(2)))
# => [[2, 4, 6, 8, 10], [12, 14, 16, 18, 20]]

Here is a version using Refinements (which is less hacky than globally monkey patching Symbol):

module AmpWithArguments

refine Symbol do
def call(*args, &block)
->(caller, *rest) { caller.send(self, *rest, *args, &block) }
end
end

end

using AmpWithArguments

a = [1,3,5,7,9]
a.map(&:+.(2))
# => [3, 5, 7, 9, 11]

[(1..5), (6..10)].map(&:map.(&:*.(2)))
# => [[2, 4, 6, 8, 10], [12, 14, 16, 18, 20]]

array_map and pass 2 arguments to the mapped function - array_map(): Argument #3 should be an array

Please always read docs:

http://php.net/manual/en/function.array-map.php

array array_map ( callable $callback , array $array1 [, array $... ] )

and yet you pass bool $format as argument

"How do you pass 2 or more arguments when you call array_map function
within a class?

I would create anonymous function with use() syntax

public function transformCollection(array $items, $format)
{
return array_map(function($item) use ($format) {
return $this->transform($item, $format);
}, $items);
}

How can i pass a single additional argument to array_map callback in PHP?

This is exactly what closures are about:

$getLimit = function($name) use ($smsPattern) {
if(preg_match($smsPattern, $name, $m)) return $m['l'];
};

$smsLimits = array_filter(array_map($getLimit, $features));

If you want to generalize it to other patterns, wrap the function creation into another function:

function patternMatcher($pattern) {
return function($name) use ($pattern) {
if(preg_match($pattern, $name, $m)) return $m['l'];
};
}

$getLimit = patternMatcher($smsPattern);
$smsLimits = array_filter(array_map($getLimit, $features));

And here it is wrapped up as an anonymous function:

$patternMatcher = function($pattern) {
return function($name) use ($pattern) {
if(preg_match($pattern, $name, $m)) return $m['l'];
};
};

$smsLimits = array_filter(array_map($patternMatcher($smsPattern), $features));

Array_map function in php with parameter

Apart from creating a mapper object, there isn't much you can do. For example:

class customMapper {
private $customMap = NULL;
public function __construct($customMap){
$this->customMap = $customMap;
}
public function map($data){
return $data[$this->customMap];
}
}

And then inside your function, instead of creating your own mapper, use the new class:

$ids = array_map(array(new customMapper('param2'), 'map'), $data['student_teacher']);

This will allow you to create a custom mapper that can return any kind of information... And you can complexify your customMapper to accept more fields or configuration easily.

Break statement in javascript array map method

That's not possible using the built-in Array.prototype.map. However, you could use a simple for-loop instead, if you do not intend to map any values:

var hasValueLessThanTen = false;
for (var i = 0; i < myArray.length; i++) {
if (myArray[i] < 10) {
hasValueLessThanTen = true;
break;
}
}

Or, as suggested by @RobW, use Array.prototype.some to test if there exists at least one element that is less than 10. It will stop looping when some element that matches your function is found:

var hasValueLessThanTen = myArray.some(function (val) { 
return val < 10;
});

How to pass standard php functions to array_map and array_filter?

You need to pass the function (user-defined OR builtin) name as a string in the parameter of array_map function.

Do the following:

$result = array_map('boolval', $elements);

Passing Additional Arguments in javascript map es6

The 2nd parameter passed to Array.map() is the thisArg, which is:

Value to use as this when executing callback.

With a standard JS function, this is defined by execution context, but you can change it using Function.bind(), and other methods.

An arrow function this is defined by the context in which it's declared, and thus cannot be changed. That's why you can use the assigned thisArg with an arrow function.

You can approximate the functionality using partial application and IIFE:

const arr = [1, 2, 3];
const result = arr.map(((m) => (n) => n + m)(5));
console.log(result);

How to skip over an element in .map()?

Just .filter() it first:

var sources = images.filter(function(img) {
if (img.src.split('.').pop() === "json") {
return false; // skip
}
return true;
}).map(function(img) { return img.src; });

If you don't want to do that, which is not unreasonable since it has some cost, you can use the more general .reduce(). You can generally express .map() in terms of .reduce:

someArray.map(function(element) {
return transform(element);
});

can be written as

someArray.reduce(function(result, element) {
result.push(transform(element));
return result;
}, []);

So if you need to skip elements, you can do that easily with .reduce():

var sources = images.reduce(function(result, img) {
if (img.src.split('.').pop() !== "json") {
result.push(img.src);
}
return result;
}, []);

In that version, the code in the .filter() from the first sample is part of the .reduce() callback. The image source is only pushed onto the result array in the case where the filter operation would have kept it.

update — This question gets a lot of attention, and I'd like to add the following clarifying remark. The purpose of .map(), as a concept, is to do exactly what "map" means: transform a list of values into another list of values according to certain rules. Just as a paper map of some country would seem weird if a couple of cities were completely missing, a mapping from one list to another only really makes sense when there's a 1 to 1 set of result values.

I'm not saying that it doesn't make sense to create a new list from an old list with some values excluded. I'm just trying to make clear that .map() has a single simple intention, which is to create a new array of the same length as an old array, only with values formed by a transformation of the old values.



Related Topics



Leave a reply



Submit