Reputation: 8742
I'm kind of new to functional programming and I try to do the following: Let's say I have an array of values: ['a','b-','c']
and I want that every item which ends with a '-'
is merged with the following array entry: ['a','b-c']
.
Of course I can do this by making a for-loop:
var test = ['a', 'b-', 'c'], result = [];
for (var i=0;i<test.length;i++) {
var curr = test[i];
if (curr.endsWith('-')) {
curr += test[i+1];
i++;
}
result.push(curr);
}
But how can one do this without the for loop?
Upvotes: 3
Views: 152
Reputation: 72957
To be honest, the way you programmed is probably the most efficient way to do this.
However, here's another option:
var test = ['a', 'b-', 'c'],
result = test.join().replace(/-,/g, '').split(',');
console.log(result);
This joins all elements into a string: 'a,b-,c'
, removes all occurrences of '-,'
> 'a,bc'
, then splits the string back up into an array with the desired result, as you can see in the output.
This can be fool-proofed a bit, by changing the separator used in the join
/ split
:
var test = ['a', 'b-', 'c'],
separator = '||',
result = test.join(separator)
.replace(new RegExp('-' + separator, 'g'), '')
.split(separator);
Upvotes: 5
Reputation: 3593
Didn't read all answers, so sry if I repeat sth. that has already been said.
Functional programming doesn't mean that there is always a predefined function that does exactly what you intend to; or a combination of some.
Sometimes it is better to write a simple short utility-function than abusing the ones that are already there.
How about some "problems" like multiple dashed-values next to each other, or at the end of the list? How do you want to handle these cases?
This would be my implementation:
function combineDashedStrings(arr){
var result = [], pending = ""
for (var i=0; i<arr.length; i++) {
var curr = pending + arr[i];
pending = curr.endsWith("-") && curr || ""; //multiple concats
//pending = !pending && curr.endsWith("-") && curr || ""; //single concat
pending || result.push(curr);
}
//pending && result.push(curr); //add last item if it contains a dash
return result
}
combineDashedStrings(['a', 'b-', 'c-', 'd', 'e-']);
feel free to switch the commented lines/options
Upvotes: 0
Reputation: 5428
This can also be achieved using Array.prototype.map
:
var test = ['a', 'b-', 'c'];
var result = test.slice().map(function (x, i, a) {
if (x.endsWith("-") && a[i+1]) {
var r = x + a[i+1]; // Join this and the next element in the array
a.splice(i, 1); // Remove the next element from the array
return r;
}
return x;
}).filter(function (x) {
return typeof x !== 'undefined';
}); // Since the array comes back with a different length and some undefined elements, remove those. Thanks @Cerbrus for pointing this out
console.log(test, result, result.length); // ["a", "b-", "c"] ["a", "b-c"] 2
Upvotes: 1
Reputation: 503
Another map
+ filter
one. Most likely slower, as filter add's another iteration through the array, but works as the original does (which is probably not what the OP wants when there are multiple -'s in a row).
var test = ['a', 'b-', 'c-', 'd', 'e'], result = [];
result = test
.map((curr, i, array) => (curr.endsWith('-') && array[i + 1] !== undefined) ? curr + array[i+1] : curr)
.filter((curr, i, arr) => (i>0 && arr[i-1].length > 1 && curr.length === 1) ? false : true)
document.write(result);
Upvotes: 0
Reputation: 126
This way will work for multiple dashed elements in a row, and if the last element has a dash, uses Array.forEach
var test = ['a', 'b-', 'c-'], result = [], next = "";
test.forEach(function(curr) {
if (curr.endsWith('-')) {
next += curr;
if (curr == test[test.length-1]) {
result.push(next);
}
}else {
result.push(next + curr);
next = "";
}
});
document.write(result);
Upvotes: 0
Reputation: 106483
One possible approach (with .reduce
):
var arr = ['a', 'b-', 'c'];
var trans = arr.reduce(function(acc, cur) {
if (acc.length && acc[acc.length - 1].slice(-1) === '-') {
acc[acc.length - 1] += cur;
}
else {
acc.push(cur);
}
return acc;
}, []);
Upvotes: 2