Map an Array Modifying Only Elements Matching a Certain Condition

Map an array modifying only elements matching a certain condition

I agree that the map statement is good as it is. It's clear and simple,, and would easy
for anyone to maintain.

If you want something more complex, how about this?

module Enumerable
def enum_filter(&filter)
FilteredEnumerator.new(self, &filter)
end
alias :on :enum_filter
class FilteredEnumerator
include Enumerable
def initialize(enum, &filter)
@enum, @filter = enum, filter
if enum.respond_to?(:map!)
def self.map!
@enum.map! { |elt| @filter[elt] ? yield(elt) : elt }
end
end
end
def each
@enum.each { |elt| yield(elt) if @filter[elt] }
end
def each_with_index
@enum.each_with_index { |elt,index| yield(elt, index) if @filter[elt] }
end
def map
@enum.map { |elt| @filter[elt] ? yield(elt) : elt }
end
alias :and :enum_filter
def or
FilteredEnumerator.new(@enum) { |elt| @filter[elt] || yield(elt) }
end
end
end

%w{ a b c }.on { |x| x == 'b' }.map { |x| x + "!" } #=> [ 'a', 'b!', 'c' ]

require 'set'
Set.new(%w{ He likes dogs}).on { |x| x.length % 2 == 0 }.map! { |x| x.reverse } #=> #<Set: {"likes", "eH", "sgod"}>

('a'..'z').on { |x| x[0] % 6 == 0 }.or { |x| 'aeiouy'[x] }.to_a.join #=> "aefiloruxy"

Arrays: conditionally mapping elements

There is no such native function because you can easily implement it yourself:

const mapWhen = (p, f) => xs => xs.map(x => p(x) ? f(x) : x);
const users = [ {id: 1, removed: true}, {id: 2, removed: true}, {id: 3, removed: true}];
console.log( mapWhen( ({id}) => id === 2, user => Object.assign({}, user, {removed: false}) ) (users));

Using array map to filter results with if conditional

You're looking for the .filter() function:

  $scope.appIds = $scope.applicationsHere.filter(function(obj) {
return obj.selected;
});

That'll produce an array that contains only those objects whose "selected" property is true (or truthy).

edit sorry I was getting some coffee and I missed the comments - yes, as jAndy noted in a comment, to filter and then pluck out just the "id" values, it'd be:

  $scope.appIds = $scope.applicationsHere.filter(function(obj) {
return obj.selected;
}).map(function(obj) { return obj.id; });

Some functional libraries (like Functional, which in my opinion doesn't get enough love) have a .pluck() function to extract property values from a list of objects, but native JavaScript has a pretty lean set of such tools.

Sum only those elements that passes the condition using map

Array#map returns a new array with the same length of the array and takes the result of the callback for every item.

Instead, you could take Array#filter which ilters the array and returns either the item or not, depending on the filter function.

const
valid = score => score >= 100,
add = (a, b) => a + b,
dolphinsGames = [97, 112, 101],
koalasGames = [109, 95, 123],
dolphinsScore = dolphinsGames.filter(valid).reduce(add, 0),
koalasScore = koalasGames.filter(valid).reduce(add, 0);

console.log(dolphinsScore, koalasScore);

if (dolphinsScore === koalasScore) console.log('draw');
else if (dolphinsScore > koalasScore) console.log('dolphins won');
else console.log('koalas won');

Array .filter and .map OR .map with a if condition

First: It's really unlikely to matter.

But: Only because it's okay in your case to have undefined in the result array, the second one will be faster.

Let's compare:

The first way, filter has to make a pass through the entire array, creating a new array with the accepted entries, then map has to make a pass through the new array and make a new array of the something properties.

The second way, map makes one pass through the array, creating a new array with the something properties (or undefined for the ones that would have been filtered out).

Of course, this assumes you aren't just offloading the burden elsewhere (e.g., if React has to do something to ignore those undefineds).

But again: It's unlikely to matter.

I would probably use a third option: Build the result array yourself:

const result = [];
for (const x of arr) {
if(someCondition) {
result[result.length] = x.something;
}
}

That still makes just one pass, but doesn't produce an array with undefined in it. (You can also shoehorn that into a reduce, but it doesn't buy you anything but complexity.)

(Don't worry about for-of requiring an iterator. It gets optimized away in "hot" code.)

Create a Map from an array of objects with a condition on array elements

Use reduce to create an object, if the key exists in the object then push to the array, otherwise create an array and push the item:

const items = [{
key: 'PRODUCT',
item_key: 'ITEM_01',
sequence: 1
},
{
key: 'STORE',
item_key: 'STORE_01',
sequence: 2
}
]

const result = items.reduce((obj, item) => {
if (!obj.hasOwnProperty(item.item_key)) {
obj[item.item_key] = [];
}

obj[item.item_key].push(item);

return obj;
}, {});

console.log(result);

How can I only keep items of an array that match a certain condition?

For this, you can use the Array#filter() method, introduced in ECMAScript5. It is supported in all browsers, except for IE8 and lower, and ancient versions of Firefox. If, for whatever reason, you need to support those browsers, you can use a polyfill for the method.

filter() takes a function as its first argument. For every item of the array, your function is passed three arguments - the value of the current item, its index in the array, and the array itself. If your function returns true (or a truthy value, e.g. 1, "pizza", or 42), that item will be included in the result. Otherwise, it won't. filter() returns a new array - your original array will be left unmodified. That means that you'll need to save the value somewhere, or it'll be lost.

Now, in the examples from the question:

var myNumbersArray = [1, 2, 3, 4, 5, 6, 7, 8];console.log(myNumbersArray.filter(function(num){  return !(num % 2); // keep numbers divisible by 2}));console.log(myNumbersArray); // see - it hasn't changed!
var myStringArray = ["This", "is", "an", "array", "with", "several", "strings", "making", "up", "a", "sentence."];console.log(myStringArray.filter(function(str){ return str.length < 3; // keep strings with length < 3}));console.log(myStringArray);
var myBoolArray = [true, false, 4, 0, "abc", "", "0"];console.log(myBoolArray.filter(Boolean));// wow, look at that trick!console.log(myBoolArray);

In Ruby, is there an Array method that combines 'select' and 'map'?

I usually use map and compact together along with my selection criteria as a postfix if. compact gets rid of the nils.

jruby-1.5.0 > [1,1,1,2,3,4].map{|n| n*3 if n==1}    
=> [3, 3, 3, nil, nil, nil]

jruby-1.5.0 > [1,1,1,2,3,4].map{|n| n*3 if n==1}.compact
=> [3, 3, 3]

JavaScript - get array element fulfilling a condition

In most browsers (not IE <= 8) arrays have a filter method, which doesn't do quite what you want but does create you an array of elements of the original array that satisfy a certain condition:

function isGreaterThanFive(x) {
return x > 5;
}

[1, 10, 4, 6].filter(isGreaterThanFive); // Returns [10, 6]

Mozilla Developer Network has a lot of good JavaScript resources.

why map() function always returns something even if condition statement does not match?_ java script

.map will always create an array with the same number of items as in the original array. That's how it works. If you don't want to produce an array with the same number of elements, use .filter instead:

let my_array = [1, 2, 4, 5, 6, 7, 8]
test = my_array.filter(element => element !== 1);

console.log(test)


Related Topics



Leave a reply



Submit