Replace an element in an array - javascript

Need to replace a value "y" with "#" in an array and also need to count the "y" value in an array.
x = ['a','b','c'];
z = ['z','y','y'];
var a = x.concat(z);
var b = a.sort();
var count = 0;
for(var i = 0; i < b.length; i++){
if(b[i] == "y") {
b['y'] == "#";
var c = count++;
}
}
console.log(b);
console.log(c+1);
Fiddle

declare all variables
assign the right value, do not make a comparison b[i] = "#";,
use count variable, and not c
no need to use b, because sort sorts the given array.
var x = ['a', 'b', 'c'];
var z = ['z', 'y', 'y'];
var a = x.concat(z);
var count = 0;
a.sort();
for (var i = 0; i < a.length; i++){
if (a[i] == "y") {
a[i] = "#";
count++;
}
}
console.log(a);
console.log(count);

You can use reduce with destructuring assignment to effectively return 2 values
var x = ['a','b','c']
var z = ['z','y','y']
var a = x.concat(z)
var [count, b] = a.reduce(([count,b],x)=> {
if (x === 'y')
return [count + 1, [...b, '#']]
else
return [count, [...b, x]]
}, [0, []])
console.log(count) // 2
console.log(b) // ['a', 'b', 'c', 'z', '#', '#']
If you really want the array sorted before replacing 'y' and getting the count, you should know that Array.prototype.sort will mutate the original array. Also, assignment of an array to a variable is by reference.
So when you write this...
var b = a.sort();
You should know that a will be sorted, and b is just a second reference to the exact same array. b is not a separate copy.
If you'd like to make a separate copy, you can do this
// make B a sorted copy of A. do not modify A.
var b = a.slice(0).sort();

== is comparison operator
= is assignment operator
Change to this :
for(var i = 0; i < b.length; i++){
if(b[i] == "y") {
b[i] = "#";
var c = count++;
}
}
from
for(var i = 0; i < b.length; i++){
if(b[i] == "y") {
b['y'] == "#";
count++;
}
}
x = ['a', 'b', 'c'];
z = ['z', 'y', 'y'];
var a = x.concat(z);
var b = a.sort();
var count = 0;
for (var i = 0; i < b.length; i++) {
if (b[i] == "y") {
b[i] = "#";
count++;
}
}
console.log(b);
console.log(count);

You can also use Array#map.
var x = ['a','b','c'];
var z = ['z','y','y'];
var a = x.concat(z);
var b = a.sort();
var count = 0;
b = b.map(function(v) {
if(v == 'y') {
count++;
return '#';
} else {
return v;
}
});
console.log(b);
console.log(count);

I'm not sure, but is this what you want?
x = ['a','b','c'];
z = ['z','y','y'];
var a = x.concat(z);
var b = a.sort();
var count = 0;
for(var i = 0; i < b.length; i++){
if(b[i] == "y") {
b[i] = "#";
var c = count++;
}
}
console.log(b);
console.log(c+1);
jsfiddle

If you are the fan of less line of code, then this one line (or maybe two line) implementation would be noticeable. ;)
BUT the main reason of my answer was about the sort return value.
as mentioned in documentation:
The sort() method sorts the elements of an array in place and returns
the array. The sort is not necessarily stable. The default sort order
is according to string Unicode code points.
So the sort() method do the action in place and returns the result (the array) too.
var x = ['a', 'b', 'c'],
z = ['z', 'y', 'y'],
toReplace = 'y',
replaceWith = '#',
count = 0;
var result = x.concat(z).sort()
.map((v, i, a) => v === toReplace ? ++count && replaceWith : v);
console.log(result, count);

Related

How to interweave two arrays in JavaScript?

I'm super confused with getting this to run, as nested loops are still a bit funny to me.
With the following two arrays:
let a = ['y','y','y'];
let z = ['x','x','x','x','x'];
How do I get it to print one value from a, and then two values from z after that so and so on?
'y',
'x',
'x',
'y',
'x',
'x',
'y',
'x',
'x'
If the values were instead:
let a = ['y','y'];
let z = ['x','x','x','x','x'];
It'd print:
'y',
'x',
'x',
'y',
'x',
'x',
'x'
This is what I've tried so far:
for (let i = 0; i < a.length; i++) {
console.log(a[i]);
for (let j = 0; j < z.length; j++) {
console.log(z[j], z[j+1]);
// break?
}
}
I repair your loop:
let a = ['y','y','y'];
let z = ['x','x','x','x','x'];
for (let i = 0; i < a.length; i++) {
console.log(a[i]);
console.log(z[i*2], z[i*2+1]);
}
`
let a = ['y','y'];
let z = ['x','x','x','x','x'];
let j = 0;
for (let i = 0; i < a.length; i++) {
console.log(a[i]);
for (j; j < z.length; j++) {
console.log(z[j], z[j+1]);
if(j % 2 == 1){
break;
}
}
}`
try this one.
One option you have is to use do/while loop. Use shift() to remove the first item.of an array
let a = ['y1', 'y2', 'y3'];
let z = ['x1', 'x2', 'x3', 'x4', 'x5', 'x6'];
//Copy the array a and z
let aTemp = [...a];
let zTemp = [...z];
do {
if (aTemp.length) console.log(aTemp.shift());
if (zTemp.length) console.log(zTemp.shift());
if (zTemp.length) console.log(zTemp.shift());
} while (aTemp.length || zTemp.length); //Loop while both the temp variables have elements
let aIndex = 0, zIndex = 0;
while(aIndex < a.length || zIndex < z.length) {
console.log(
a[aIndex++],
z[zIndex++],
z[zIndex++]
);
}
Here is non destructive way of doing this
var pointer = 0;
for (let i = 0; i < a.length; i++) {
var count = 0;
console.log(a[i]);
for (let j = pointer; j < z.length; j++) {
console.log(z[j]);
count++;
if(count == 2){
count = 0;
if(i == a.length-1) { continue; }else { pointer = j+1; break; }
}
}
}
let c = j = 0;
z.map(function(item){
if(c === 0 && a[j]){ console.log(a[j++]); }
console.log(item);
c = c > 0 ? 0 : c + 1;
});
Please have a look at the below code. I pushed your expected output result in to an array.
let a = ['y','y'];
let z = ['x', 'x', 'x', 'x', 'x'];
let arr = [];
for (let i = 0; i < a.length; i++) {
var count = 0
arr.push(a[i]);
for (let j = i * 2; j < z.length; j++) {
arr.push(z[j]);
count++
if (count > 1) {
if (z[j+1] !== undefined && a[i+1] === undefined) {
for (let k = j+1; k < z.length; k++) {
arr.push(z[k])
}
}
break;
}
}
}
console.log(arr);
// ["y", "x", "x", "y", "x", "x", "x"]
You don't need a nested loop at all. This can be done with a single loop with two counters.
let a = ['y','y','y'];
let z = ['x','x','x','x','x'];
let result = [];
for(let i = 0, j = 0; i < a.length, j < z.length; i++, j+=2) {
result.push(a[i], z[j], z[j+1]);
}
result = result.filter(item => item !== undefined);
console.log(result);
And here's the same code condensed to a one-liner core:
let a = ['y','y','y'];
let z = ['x','x','x','x','x'];
let result = [];
for(let i = 0, j = 0; i < a.length, j < z.length; i++, j+=2) {
result.push.apply(result, [a[i], z[j], z[j+1]].filter(m => m !== undefined));
}
console.log(result);
You could take the length and calculate the interval/part lenght of the array for splicing and pushing to the result set.
function getX(a, b) {
var iA = Math.ceil(a.length / b.length),
iB = Math.ceil(b.length / a.length),
pA = 0,
pB = 0,
result = [];
while (pA < a.length || pB < b.length) {
result.push(
...a.slice(pA, pA += iA),
...b.slice(pB, pB += iB)
);
}
return result;
}
console.log(getX(['y','y','y'], ['x','x','x','x','x']).join(' '));
console.log(getX(['y','y'], ['x','x','x','x','x']).join(' '));
Here is an example using Array.prototype.reduce() and a destructuring assignment:
let a = ["y", "y", "y"];
let z = ["x", "x", "x", "x", "x"];
let y = a.reduce((acc, current, index) => {
return [...acc, current, ...z.splice(0, a[index + 1] ? 2 : z.length)];
}, []);
console.log(y);
console.log(z);
On every a array element you take previously accumulated array (initially []), add current element and two elements from z if a has next element or the rest of z elements if current is the last element of a.
This unfortunately deletes elements from z in the process, so you might want to copy it before running it, i.e. you can wrap reduce in a function and pass a copy of z:
let a = ["y", "y", "y"];
let z = ["a", "b", "c", "d", "e", "f", "g"];
const interweave = (arr1, arr2) => {
return arr1.reduce((acc, current, index) => {
return [
...acc,
current,
...arr2.splice(0, arr1[index + 1] ? 2 : arr2.length)
];
}, []);
};
console.log(interweave(a, [...z]));
console.log(z);
You can do it without any for or while too! try this:
let a = ['y','y','y'];
let z = ['x','x','x','x','x'];
console.log(
[].concat.apply([], a.map(function(m, i){return [m].concat(z.slice(i*2, i*2+2));}))
);
Now you can join the result if you want like this:
let a = ['y','y','y'];
let z = ['x','x','x','x','x'];
console.log(
[].concat.apply([], a.map(function(m, i){return [m].concat(z.slice(i*2, i*2+2));})).join(",")
);
Or if you like reduce function, you can try this:
let a = ['y','y','y'];
let z = ['x','x','x','x','x'];
console.log(
a.reduce(function(ac, m, i){return ac.push.apply(ac, [m].concat(z.slice(i*2, i*2+2))), ac;}, [])
);

EloquentJavascript: reverseArrayInPlace function. Is this an acceptable code or would this be considered poor logic? [duplicate]

I'm trying to solve the following exercise:
Reverse an array without using the reverse method, without using a
second array, and without duplicating any of the values.
I've thought about making the array an object and then updating the array from the end to the beginning but I figured you can just update it as well.
Tried something simple like:
function reverseArray(array) {
for (var i = 0; i < array.length; i++) {
// var elem = array.shift();
var elem = array.shift()
array.push(elem)
}
return array
}
array = ['a', 'b','c','d','e'];
reverseArray(array);
But that doesn't really change it. Any advice or explanation on how to do this?
With ES6 syntax you don't need to copy a value into a temporary variable (is that what the last requirement is about?).
function reverse(arr) {
for(let i = 0, j = arr.length-1; i < j; i++, j--)
[arr[i], arr[j]] = [arr[j], arr[i]];
}
const arr = ['a','b','c','d','e'];
reverse(arr);
console.log(arr);
One may argue that arrays are created here (if engines don't optimise this away), just like splice also creates an array (as its return value).
array = ['a', 'b', 'c', 'd', 'e'];
console.log(array);
for (var i = 0; i < Math.floor(array.length / 2); i++) {
var item = array[i];
array[i] = array[array.length - i - 1];
array[array.length - i - 1] = item;
}
console.log(array);
Here is a minimal approach. Given var arr = [1,2,3,4], this loop will mutate arr to [4,3,2,1]:
for (var i = 0; i < arr.length - 1; i++) {
arr.splice(i, 0, arr.pop());
}
The following will work reverse an array without using the reverse method. It works by swapping the first and last elements, then the second and second-to-last elements, then the third and third-to-last elements, etc until the i is no longer less than (<) than j.
function reverse(arr) {
for(var i = 0, j = arr.length-1; i < j; i++, j--) {
var tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
return arr;
};
var reversed = reverse(['a','b','c','d','e']);
console.log(reversed);
https://jsfiddle.net/pa2fqa8n/1/
a = ['a', 'b', 'c', 'd', 'e'];
for(var i = 0; i < a.length-1; i++){
for(var j = 0; j < a.length-i-1; j++){
var k = a[j];
a[j] = a[j+1];
a[j+1] = k;
}
}
First iteration of inner loop moves the first element to the end, and the rest of the elements forward once. Each following iteration does the same thing, but 1 less than the previous iteration.
I had to use a swap variable, does that violate "without duplicating any of the values"?
var test1 = [2, '5', 6, 'a', 'Z'];
var test2 = [2, '5', false, 'a', 'Z', {a: 'whatevs'}];
console.log('test1 before', JSON.stringify(test1));
console.log('test2 before', JSON.stringify(test2));
reversarooni(test1);
reversarooni(test2);
console.log('test1 after', JSON.stringify(test1));
console.log('test2 after', JSON.stringify(test2));
function reversarooni(inputArray) {
var index = 0;
var len = inputArray.length;
for(; index < len / 2; index++) {
var swap = inputArray[index];
inputArray[index] = inputArray[(len - 1) - index];
inputArray[(len - 1) - index] = swap;
}
}
Here's how, without copies, temporary arrays or variables to hold values, or using Array.reverse().Modifying the array in place
function reverseArray(array) {
var len = array.length;
for (var i=len,j=-1; j++,i--;) array.unshift( array[len-1-i+(j)] );
array.length = len;
}
var array = ['a', 'b','c','d','e'];
reverseArray(array);
console.log(array);
It inserts the values backwards into the beginning of the array, pushing the old values to the end, and then slicing them of by resetting the arrays length after the iteration has completed.
You could use a spread syntax ..., rest parameters ... and return the swapped items with a recursive and functional approach.
const
_ = (...a) => a,
rev = (a, ...rest) => rest.length ? _(...rev(...rest), a) : _(a),
reverseArray = array => rev(...array);
console.log(reverseArray(['a', 'b', 'c', 'd', 'e']));
console.log(reverseArray(['a']));
console.log(reverseArray(['a', 'b']));
.as-console-wrapper { max-height: 100% !important; top: 0; }
function reverseArray(a) {
const halfLength = a.length / 2;
for (let i = 0; i< halfLength; i++){
const start = a[i]
a[i] = a[a.length-i-1]
a[a.length-i-1] = start
}
return a;
}
function printReverse(array) {
for (i = array.length-1; i > -1; i--) {
console.log(array[i]); //4,3,2,1
}
}
printReverse([1, 2, 3, 4]);
This worked for me.

Reversing an array without 'reverse' or duplicating an array

I'm trying to solve the following exercise:
Reverse an array without using the reverse method, without using a
second array, and without duplicating any of the values.
I've thought about making the array an object and then updating the array from the end to the beginning but I figured you can just update it as well.
Tried something simple like:
function reverseArray(array) {
for (var i = 0; i < array.length; i++) {
// var elem = array.shift();
var elem = array.shift()
array.push(elem)
}
return array
}
array = ['a', 'b','c','d','e'];
reverseArray(array);
But that doesn't really change it. Any advice or explanation on how to do this?
With ES6 syntax you don't need to copy a value into a temporary variable (is that what the last requirement is about?).
function reverse(arr) {
for(let i = 0, j = arr.length-1; i < j; i++, j--)
[arr[i], arr[j]] = [arr[j], arr[i]];
}
const arr = ['a','b','c','d','e'];
reverse(arr);
console.log(arr);
One may argue that arrays are created here (if engines don't optimise this away), just like splice also creates an array (as its return value).
array = ['a', 'b', 'c', 'd', 'e'];
console.log(array);
for (var i = 0; i < Math.floor(array.length / 2); i++) {
var item = array[i];
array[i] = array[array.length - i - 1];
array[array.length - i - 1] = item;
}
console.log(array);
Here is a minimal approach. Given var arr = [1,2,3,4], this loop will mutate arr to [4,3,2,1]:
for (var i = 0; i < arr.length - 1; i++) {
arr.splice(i, 0, arr.pop());
}
The following will work reverse an array without using the reverse method. It works by swapping the first and last elements, then the second and second-to-last elements, then the third and third-to-last elements, etc until the i is no longer less than (<) than j.
function reverse(arr) {
for(var i = 0, j = arr.length-1; i < j; i++, j--) {
var tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
return arr;
};
var reversed = reverse(['a','b','c','d','e']);
console.log(reversed);
https://jsfiddle.net/pa2fqa8n/1/
a = ['a', 'b', 'c', 'd', 'e'];
for(var i = 0; i < a.length-1; i++){
for(var j = 0; j < a.length-i-1; j++){
var k = a[j];
a[j] = a[j+1];
a[j+1] = k;
}
}
First iteration of inner loop moves the first element to the end, and the rest of the elements forward once. Each following iteration does the same thing, but 1 less than the previous iteration.
I had to use a swap variable, does that violate "without duplicating any of the values"?
var test1 = [2, '5', 6, 'a', 'Z'];
var test2 = [2, '5', false, 'a', 'Z', {a: 'whatevs'}];
console.log('test1 before', JSON.stringify(test1));
console.log('test2 before', JSON.stringify(test2));
reversarooni(test1);
reversarooni(test2);
console.log('test1 after', JSON.stringify(test1));
console.log('test2 after', JSON.stringify(test2));
function reversarooni(inputArray) {
var index = 0;
var len = inputArray.length;
for(; index < len / 2; index++) {
var swap = inputArray[index];
inputArray[index] = inputArray[(len - 1) - index];
inputArray[(len - 1) - index] = swap;
}
}
Here's how, without copies, temporary arrays or variables to hold values, or using Array.reverse().Modifying the array in place
function reverseArray(array) {
var len = array.length;
for (var i=len,j=-1; j++,i--;) array.unshift( array[len-1-i+(j)] );
array.length = len;
}
var array = ['a', 'b','c','d','e'];
reverseArray(array);
console.log(array);
It inserts the values backwards into the beginning of the array, pushing the old values to the end, and then slicing them of by resetting the arrays length after the iteration has completed.
You could use a spread syntax ..., rest parameters ... and return the swapped items with a recursive and functional approach.
const
_ = (...a) => a,
rev = (a, ...rest) => rest.length ? _(...rev(...rest), a) : _(a),
reverseArray = array => rev(...array);
console.log(reverseArray(['a', 'b', 'c', 'd', 'e']));
console.log(reverseArray(['a']));
console.log(reverseArray(['a', 'b']));
.as-console-wrapper { max-height: 100% !important; top: 0; }
function reverseArray(a) {
const halfLength = a.length / 2;
for (let i = 0; i< halfLength; i++){
const start = a[i]
a[i] = a[a.length-i-1]
a[a.length-i-1] = start
}
return a;
}
function printReverse(array) {
for (i = array.length-1; i > -1; i--) {
console.log(array[i]); //4,3,2,1
}
}
printReverse([1, 2, 3, 4]);
This worked for me.

How to slice array values by two

I have a javascript array of values [A,B,C,D,E.....] that i need to split with this syntax:
[ [A, B], [C, D], [E, F] ]
and so on (it will be always a pair).
So it should be a loop that returns a string.
I've tried to do like so, and it's almost what i wanted:
text = '['+array[0]+','+array[1]+']';
for (index = 2; index < array.length; index++) {
text += '['+array[index]+','+array[index+1]+']';
console.log(text);
}
I get
[10:00,15:45][18:30,20:00]
[10:00,15:45][18:30,20:00][20:00,undefined]
instead i need to get only this:
[10:00,15:45][18:30,20:00]
Could try making text an actual array and pushing pairs in, like so
var orig=['A','B','C','D','E','F'];
var text=[];
for (index = 0; index < orig.length-1; index+=2) {
text.push([orig[index],orig[index+1]]);
console.log(JSON.stringify(text));
}
Here's a small method for grouping array elements. You can just check that your inner arrays have a length of 2 afterwards, if you only care about pairs.
if (!Array.prototype.group) {
Array.prototype.group = function (length) {
var a = this.slice(), r = [];
length = length || 1;
while (a.length > 0) {
r.push(a.splice(0, length));
}
return r;
};
}
var arr = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'].group(2);
console.log(arr);
A version for if you want to discard a final group that doesn't match your expected length.
if (!Array.prototype.group) {
Array.prototype.group = function (length, req) {
var a = this.slice(), r = [], h;
length = length || 1;
while (a.length > 0) {
h = a.splice(0, length);
if (!req || h.length === length) {
r.push(h);
}
}
return r;
};
}
var arr = ['an', 'odd', 'number', 'of', 'elements'].group(2, true);
console.log(arr)
Something in the lines of:
var groupArray = function(arr){
var groupedArray = [];
for(var i = 0, len = arr.length; i < len; i += 2){
groupedArray.push([arr[i], arr[i + 1]]);
}
return groupedArray;
};
This obviously only works for arrays with an even number of elements. If you need the function to work with arrays with an odd number of elements, too, you need to acomodate for that.

Replace array values with new defined values in Javascript

//Get message from textarea
var msg = $('#mytextarea').val();
//Convert string to array of letters
// eg. cata = ['c','a','t','a']
var msgLettersAsArray = msg.split('');
What I need to do now is replace the single letters,something like this
c = b;
a = e;
t = c;
a = e;
//array neeeds to be converted from this:
var array = ['c','a','t','a'];
// to this:
var array = ['b','e','c','e'];
Is there any way to achieve this?
All I need to do is replace the letters that are already in the array with letters of my choice
It's quite simple, just define a translation map and use Array.prototype.map.
var translationMap = {
c: 'b',
a: 'e',
t: 'c'
};
//returns ['b','e','c','e']
['c','a','t','a'].map(function (letter) { return translationMap[letter] || letter; });
EDIT: It seems you actually just wanted to replace letters in the string, in this case #phylax answer would be correct. There is no need to use arrays for a simple string replacement.
function replaceChars(str, map) {
var i, reg = "";
for (i in map)
reg += i;
return str.replace(
new RegExp("["+reg.replace(/(\]|-|\\)/,"\\$1")+"]",'g'),
function(char) { return map[char]; }
);
}
//Get message from textarea
var msg = $('#mytextarea').val(); // "cata"
replaceChars(msg, {c:'b', a:'e', t:'c', a:'e'}); // "bece"
Just making an answer out of my comment:
Like OP said, its ok to be done without the split(). And its possible to do with only one call to String.replace():
var map = {
c: 'b',
a: 'e',
t: 'c'
};
msg.replace(/[a-z0-9]/g, function (i) { return map[i] || i; })
The RegExp can possibly made event simpler:
msg.replace(/./g, function (i) { return map[i] || i; })
Sure, just use a for loop:
var array = ['c','a','t','a'];
for (var i = 0; i < array.length; i++)
{
var cur = array[i];
if (cur == 'c') {
array[i] = 'b';
} else if (cur == 'a') {
array[i] = 't';
} else if (cur == 't') {
array[i] = 'c';
}
}
But using an object to store these mappings can make your code even more compact:
var array = ['c','a','t','a'];
var transform = { 'c': 'b', 'a': 'e', 't': 'c' };
for (var i = 0; i < array.length; i++)
{
array[i] = transform[array[i]];
}
not tested but it should work
var replaxe = {
'c':'b',
'e':'d'
},
array = ['c','e'],
result = [];
for(var item in array){
result.push(replaxe[item]);
}
console.log(result);
RUN THIS IN YOUR FIRE BUG CONSOLE
var array = ['c','a','t','a'];
var myarray = [];
for(i=0; i<=array.length; i++)
{
if(array[i] == 'c' )
{
array[i] = 'b'
}
if(array[i] == 'a' )
{
array[i] = 'e'
}
if(array[i] == 't' )
{
array[i] = 'c'
}
if(array[i] == 'a' )
{
array[i] = 'a'
}
}
console.log(myarray);
I would recommend using a switch-case for every element in the array.
for (i in array) {
switch (array[i]) {
case "c":
array[i] = "b";
break;
case "a":
array[i] = "e";
break;
case "t":
array[i] = "c";
break;
}
}

Categories