using array.map with repeat in Javascript - javascript

Hello I have the following:
var a = [1, 2, 3]
I would like to update this array to:
a = [11,22,33]
I am trying to do something like
a.map(repeat(2));
but it results in an error.
I know I could easily loop through this, but I am trying to practice using more concise code, and expand my knowledge a bit on different functions, and how to use them.
Is something like this possible?

You could convert the number to string, repeat the value and convert it back to number.
var a = [1, 2, 3]
a = a.map(a => +a.toString().repeat(2));
console.log(a);

Given that you seem to be looking for repeating the digits, use strings for that. Which have a handy repeat method for this purpose:
a.map(x => Number(String(x).repeat(2))));
If you want to use your notation, you need to make a higher-order repeat function that returns another function to be used as the map callback:
function repeat(times) {
return x => String(x).repeat(times);
}
a.map(repeat(2)).map(Number)

Yes that is possible. You can define repeat as a function that returns a function:
function repeat(times) {
return function (value) {
return +String(value).repeat(times);
}
}
// Your code:
var a = [1, 2, 3];
var result = a.map(repeat(2));
console.log(result);
The map method expects a function as argument, so the call to repeat(2) should return a function. That (inner) function uses String#repeat after converting the value to string, and then converts the result back to number with the unary +.

Here you go, number version and string version
const doubleIt = n => Number(`${n}${n}`);
const arr = [1, 2, 3, 55];
const strArr = arr.map(o => `${o}${o}`);
const numArr = arr.map(o => o * 11);
const numFromStringsArr = arr.map(o => doubleIt(o));
console.log(strArr);
console.log(numArr);
console.log(numFromStringsArr);

You can create an array of N .length with Array(), use Array.prototype.fill() to fill the created array with current element of .map() callback, chain Array.prototype.join() with "" as parameter, use + operator to convert string to number
var a = [1, 2, 3], n = 2;
a = a.map(el => +Array(n).fill(el).join(""));
console.log(a);

Simply, try it with Array join() method:
a.map(x => Array(2).join(x));

Related

Array of numbers to Array of one string

I need to [1, 2, 3] over to ['123'].
I must return [1, 2, 3] over to ['123'] while using an arrow function (no regex):
Must be used:
const functionOne = (arrayOne) => {
};
console.log(functionOne([1, 2, 3]));
So, I tried the following:
First, I created a string. This gave me 1,2,3
Then, I removed the commas, so, I could join the numbers. This gave me 123.
Finally, I tried to put back the number as a string into the array but this didn't work. This gave me ['1', '2', '3'] instead of ['123']. I think the .split method is what is wrong in my code but I cannot find another one (currently learning JavaScript).
const functionOne = (arrayOne) => {
let stepOne = arrayOne.toString(arrayOne => arrayOne.toString());
console.log(stepOne);
stepOne = stepOne.split(',').join('');
console.log(stepOne);
return stepOne.split('');
};
console.log(functionOne([1, 2, 3]));
You can join using "" as the delimiter (it will automatically convert the elements to strings as it produces the output string), then put the result in an array as its only element ([____]):
const functionOne = (array) => [array.join("")];
console.log(functionOne([1, 2, 3]));
Issues with your original approach:
Array's toString completesly ignores the argument you're giving it, instead using its default behavior of join(",").
Splitting it on , again just gives you back an array, but this time of strings.
Rejoining that with join('') does give you "123", but doesn't put it in an array.
You could take a recursive function.
const
fn = ([v, ...rest]) => rest.length
? [v + fn(rest)]
: [v];
console.log(fn([1, 2, 3]));
const functionOne = (arrayOne) => {
let stepOne = arrayOne.toString();
stepOne = stepOne.split(',').join('');
return [stepOne];
};
console.log(functionOne([1, 2, 3]));
The .toString() method will convert the array [1, 2, 3] to the string "1,2,3", then .split(',').join('') removes the commas and joins the numbers as a single string "123". Finally, return [stepOne]; returns the string "123" inside an array ['123'].

Sorting array multiple times and storing in an object [duplicate]

Let's suppose I wanted a sort function that returns a sorted copy of the inputted array. I naively tried this
function sort(arr) {
return arr.sort();
}
and I tested it with this, which shows that my sort method is mutating the array.
var a = [2,3,7,5,3,7,1,3,4];
sort(a);
alert(a); //alerts "1,2,3,3,3,4,5,7,7"
I also tried this approach
function sort(arr) {
return Array.prototype.sort(arr);
}
but it doesn't work at all.
Is there a straightforward way around this, preferably a way that doesn't require hand-rolling my own sorting algorithm or copying every element of the array into a new one?
You need to copy the array before you sort it. One way with es6:
const sorted = [...arr].sort();
The spread-syntax as array literal (copied from mdn):
var arr = [1, 2, 3];
var arr2 = [...arr]; // like arr.slice()
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator
Just copy the array. There are many ways to do that:
function sort(arr) {
return arr.concat().sort();
}
// Or:
return Array.prototype.slice.call(arr).sort(); // For array-like objects
Try the following
function sortCopy(arr) {
return arr.slice(0).sort();
}
The slice(0) expression creates a copy of the array starting at element 0.
You can use slice with no arguments to copy an array:
var foo,
bar;
foo = [3,1,2];
bar = foo.slice().sort();
You can also do this
d = [20, 30, 10]
e = Array.from(d)
e.sort()
This way d will not get mutated.
function sorted(arr) {
temp = Array.from(arr)
return temp.sort()
}
//Use it like this
x = [20, 10, 100]
console.log(sorted(x))
Update - Array.prototype.toSorted() proposal
The Array.prototype.toSorted(compareFn) -> Array is a new method which was proposed to be added to the Array.prototype and is currently in stage 3 (Soon to be available).
This method will keep the target Array untouched and returns a copy of it with the change performed instead.
Anyone who wants to do a deep copy (e.g. if your array contains objects) can use:
let arrCopy = JSON.parse(JSON.stringify(arr))
Then you can sort arrCopy without changing arr.
arrCopy.sort((obj1, obj2) => obj1.id > obj2.id)
Please note: this can be slow for very large arrays.
Try this to sort the numbers. This does not mutate the original array.
function sort(arr) {
return arr.slice(0).sort((a,b) => a-b);
}
There's a new tc39 proposal, which adds a toSorted method to Array that returns a copy of the array and doesn't modify the original.
For example:
const sequence = [3, 2, 1];
sequence.toSorted(); // => [1, 2, 3]
sequence; // => [3, 2, 1]
As it's currently in stage 3, it will likely be implemented in browser engines soon, but in the meantime a polyfill is available here or in core-js.
I think that my answer is a bit too late but if someone come across this issue again the solution may be useful.
I can propose yet another approach with a native function which returns a sorted array.
This code still mutates the original object but instead of native behaviour this implementation returns a sorted array.
// Remember that it is not recommended to extend build-in prototypes
// or even worse override native functions.
// You can create a seperate function if you like
// You can specify any name instead of "sorted" (Python-like)
// Check for existence of the method in prototype
if (typeof Array.prototype.sorted == "undefined") {
// If it does not exist you provide your own method
Array.prototype.sorted = function () {
Array.prototype.sort.apply(this, arguments);
return this;
};
}
This way of solving the problem was ideal in my situation.
You can also extend the existing Array functionality. This allows chaining different array functions together.
Array.prototype.sorted = function (compareFn) {
const shallowCopy = this.slice();
shallowCopy.sort(compareFn);
return shallowCopy;
}
[1, 2, 3, 4, 5, 6]
.filter(x => x % 2 == 0)
.sorted((l, r) => r - l)
.map(x => x * 2)
// -> [12, 8, 4]
Same in typescript:
// extensions.ts
Array.prototype.sorted = function (compareFn?: ((a: any, b: any) => number) | undefined) {
const shallowCopy = this.slice();
shallowCopy.sort(compareFn);
return shallowCopy;
}
declare global {
interface Array<T> {
sorted(compareFn?: (a: T, b: T) => number): Array<T>;
}
}
export {}
// index.ts
import 'extensions.ts';
[1, 2, 3, 4, 5, 6]
.filter(x => x % 2 == 0)
.sorted((l, r) => r - l)
.map(x => x * 2)
// -> [12, 8, 4]

Is it possible to "overwrite a pointer" in JavaScript?

Is it possible to emulate the code below, in JavaScript?
var ref = new Reference();
var arr = [1, 2, ref];
ref.overwrite(3);
console.log(arr); // output: [1,2,3]
This code places a ref inside an array, then overwrites it, completely replacing its occurrence by 3. We could do something similar by storing the parent object and the index:
var arr = [1, 2, null];
var ref = {object: arr, index: 2};
ref.object[ref.index] = 3;
console.log(arr); // output: [1, 2, 3]
But this is not the same thing, since ref must keep track of all the parent objects where it is used. I'm interested in using ref as a placeholder, storing it in multiple places and then replacing all occurrences by something else, without keeping track of where it was used. We could also "almost" do this as such:
var ref = {value: null};
var arr = [1, 2, ref];
ref.value = 3;
console.log(arr); // output: [1, 2, {value: 3}]
But this doesn't completely get rid of the wrapping object.
No, JavaScript does not have references or pointers as values. You always need some wrapper object (which you can mutate however you want, but not replace), it's not possible to create a custom primitive value.
There is no way to really do what you want to do, but depending on how you are using it, you can fake it. You can use valueOf to return what you want. Example here shows using it to sum up an array of numbers and than altering it and running it again.
const sum = arr => arr.reduce((t, i) => t + i, 0)
function MyRef(n) {
this.number = n;
this.overWrite = n => this.number = n
}
MyRef.prototype.valueOf = function() {
return this.number;
};
const ref = new MyRef(100);
const myArray = [1, 2, ref]
console.log(sum(myArray))
ref.overWrite(3)
console.log(sum(myArray))

How do I replace an array element without modifying the original array and creating copy?

I'm trying to create a pure function that receives an array as parameter and now I want to replace an element at a given index without modifying the provided array argument.
Basically I'm looking for something like this:
export const muFunc = (arr) => {
return arr.replaceElementAt(1, 'myNewValue'); // This doesnt modify arr at all
}
How can I do that?
Simply copy the array. A simple way to do that is slice:
export const muFunc = (arr) => {
var newArray = arr.slice();
newArray[1] = 'myNewValue';
return newArray;
};
From a comment on the question:
As the topic says - I'm trying to find out if it's possible without creating a copy of the array
No it's not possible — well, not reasonably. You have to either modify the original, or make a copy.
You could create proxy object that just returns a different value for the "1" property, but that seems unnecessarily complicated.
You could take advantage of Object.assign and do something like:
const arr = [1, 2, 3, 4, 5];
const updatedArr = Object.assign([], arr, {1: 'myNewValue'});
console.log(arr); // [1, 2, 3, 4, 5]
console.log(updatedArr); // [1, "myNewValue", 3, 4, 5]
You can use map function to achieve this
var arr = [1,2,3,4,5,6,7,89];
arr.map(function (rm) {
if (rm == 2) {
return 3
} else {
return rm
}
})
Try this :
function replace(l) {
return l.splice("new value",1);
};
var x = replace(arr);

How can you sort an array without mutating the original array?

Let's suppose I wanted a sort function that returns a sorted copy of the inputted array. I naively tried this
function sort(arr) {
return arr.sort();
}
and I tested it with this, which shows that my sort method is mutating the array.
var a = [2,3,7,5,3,7,1,3,4];
sort(a);
alert(a); //alerts "1,2,3,3,3,4,5,7,7"
I also tried this approach
function sort(arr) {
return Array.prototype.sort(arr);
}
but it doesn't work at all.
Is there a straightforward way around this, preferably a way that doesn't require hand-rolling my own sorting algorithm or copying every element of the array into a new one?
You need to copy the array before you sort it. One way with es6:
const sorted = [...arr].sort();
The spread-syntax as array literal (copied from mdn):
var arr = [1, 2, 3];
var arr2 = [...arr]; // like arr.slice()
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator
Just copy the array. There are many ways to do that:
function sort(arr) {
return arr.concat().sort();
}
// Or:
return Array.prototype.slice.call(arr).sort(); // For array-like objects
Try the following
function sortCopy(arr) {
return arr.slice(0).sort();
}
The slice(0) expression creates a copy of the array starting at element 0.
You can use slice with no arguments to copy an array:
var foo,
bar;
foo = [3,1,2];
bar = foo.slice().sort();
You can also do this
d = [20, 30, 10]
e = Array.from(d)
e.sort()
This way d will not get mutated.
function sorted(arr) {
temp = Array.from(arr)
return temp.sort()
}
//Use it like this
x = [20, 10, 100]
console.log(sorted(x))
Update - Array.prototype.toSorted() proposal
The Array.prototype.toSorted(compareFn) -> Array is a new method which was proposed to be added to the Array.prototype and is currently in stage 3 (Soon to be available).
This method will keep the target Array untouched and returns a copy of it with the change performed instead.
Anyone who wants to do a deep copy (e.g. if your array contains objects) can use:
let arrCopy = JSON.parse(JSON.stringify(arr))
Then you can sort arrCopy without changing arr.
arrCopy.sort((obj1, obj2) => obj1.id > obj2.id)
Please note: this can be slow for very large arrays.
Try this to sort the numbers. This does not mutate the original array.
function sort(arr) {
return arr.slice(0).sort((a,b) => a-b);
}
There's a new tc39 proposal, which adds a toSorted method to Array that returns a copy of the array and doesn't modify the original.
For example:
const sequence = [3, 2, 1];
sequence.toSorted(); // => [1, 2, 3]
sequence; // => [3, 2, 1]
As it's currently in stage 3, it will likely be implemented in browser engines soon, but in the meantime a polyfill is available here or in core-js.
I think that my answer is a bit too late but if someone come across this issue again the solution may be useful.
I can propose yet another approach with a native function which returns a sorted array.
This code still mutates the original object but instead of native behaviour this implementation returns a sorted array.
// Remember that it is not recommended to extend build-in prototypes
// or even worse override native functions.
// You can create a seperate function if you like
// You can specify any name instead of "sorted" (Python-like)
// Check for existence of the method in prototype
if (typeof Array.prototype.sorted == "undefined") {
// If it does not exist you provide your own method
Array.prototype.sorted = function () {
Array.prototype.sort.apply(this, arguments);
return this;
};
}
This way of solving the problem was ideal in my situation.
You can also extend the existing Array functionality. This allows chaining different array functions together.
Array.prototype.sorted = function (compareFn) {
const shallowCopy = this.slice();
shallowCopy.sort(compareFn);
return shallowCopy;
}
[1, 2, 3, 4, 5, 6]
.filter(x => x % 2 == 0)
.sorted((l, r) => r - l)
.map(x => x * 2)
// -> [12, 8, 4]
Same in typescript:
// extensions.ts
Array.prototype.sorted = function (compareFn?: ((a: any, b: any) => number) | undefined) {
const shallowCopy = this.slice();
shallowCopy.sort(compareFn);
return shallowCopy;
}
declare global {
interface Array<T> {
sorted(compareFn?: (a: T, b: T) => number): Array<T>;
}
}
export {}
// index.ts
import 'extensions.ts';
[1, 2, 3, 4, 5, 6]
.filter(x => x % 2 == 0)
.sorted((l, r) => r - l)
.map(x => x * 2)
// -> [12, 8, 4]

Categories

Resources