Wannabe Array to Array - javascript

I'm trying to take an object that looks like this : [ '1,23' , '4,56' , '7,89' ] to an Array. Although it looks like one, it isnt. It is an typeof acuses it as a object.
I tried toArray, forEach, splice with comma (cant due to the middle numbers).
Anyway, can anyone give me a hand. I'm trying really hard with something that , at least, looks easy.

JavaScript's typeof does not have a separate value for array, it returns "object". You can check if a value is an array with the Array.isArray function.
var a = [1, 2, 3];
typeof a == "object"
Array.isArray(a) == true

Something like this, by replacing each element's , with . and then parsing.
const input = ['1,23', '4,56', '7,89']
const outputString = input.map(it => it.replace(',', '.'))
const outputFloat = input.map(it => it.replace(',', '.')).map(it => parseFloat(it))
console.log(outputString)
console.log(outputFloat)

To convert the array of strings to an array of numbers, you can use map and parseFloat to get the strings to numbers as well as replace to swap the "," for a "." for each string..
var arr = [ '1,23' , '4,56' , '7,89' ];
var newArr = arr.map(item => parseFloat(item.replace(/,/,'.')))
console.log(newArr); // gives [1.23, 4.56, 7.89]

Related

pushing into an array inside an object using function it's returning Number instead of the value of pushed array [duplicate]

Are there any substantial reasons why modifying Array.push() to return the object pushed rather than the length of the new array might be a bad idea?
I don't know if this has already been proposed or asked before; Google searches returned only a myriad number of questions related to the current functionality of Array.push().
Here's an example implementation of this functionality, feel free to correct it:
;(function() {
var _push = Array.prototype.push;
Array.prototype.push = function() {
return this[_push.apply(this, arguments) - 1];
}
}());
You would then be able to do something like this:
var someArray = [],
value = "hello world";
function someFunction(value, obj) {
obj["someKey"] = value;
}
someFunction(value, someArray.push({}));
Where someFunction modifies the object passed in as the second parameter, for example. Now the contents of someArray are [{"someKey": "hello world"}].
Are there any drawbacks to this approach?
See my detailed answer here
TLDR;
You can get the return value of the mutated array, when you instead add an element using array.concat[].
concat is a way of "adding" or "joining" two arrays together. The awesome thing about this method, is that it has a return value of the resultant array, so it can be chained.
newArray = oldArray.concat[newItem];
This also allows you to chain functions together
updatedArray = oldArray.filter((item) => {
item.id !== updatedItem.id).concat[updatedItem]};
Where item = {id: someID, value: someUpdatedValue}
The main thing to notice is, that you need to pass an array to concat.
So make sure that you put your value to be "pushed" inside a couple of square brackets, and you're good to go.
This will give you the functionality you expected from push()
You can use the + operator to "add" two arrays together, or by passing the arrays to join as parameters to concat().
let arrayAB = arrayA + arrayB;
let arrayCD = concat(arrayC, arrayD);
Note that by using the concat method, you can take advantage of "chaining" commands before and after concat.
Are there any substantial reasons why modifying Array.push() to return the object pushed rather than the length of the new array might be a bad idea?
Of course there is one: Other code will expect Array::push to behave as defined in the specification, i.e. to return the new length. And other developers will find your code incomprehensible if you did redefine builtin functions to behave unexpectedly.
At least choose a different name for the method.
You would then be able to do something like this: someFunction(value, someArray.push({}));
Uh, what? Yeah, my second point already strikes :-)
However, even if you didn't use push this does not get across what you want to do. The composition that you should express is "add an object which consist of a key and a value to an array". With a more functional style, let someFunction return this object, and you can write
var someArray = [],
value = "hello world";
function someFunction(value, obj) {
obj["someKey"] = value;
return obj;
}
someArray.push(someFunction(value, {}));
Just as a historical note -- There was an older version of JavaScript -- JavaScript version 1.2 -- that handled a number of array functions quite differently.
In particular to this question, Array.push did return the item, not the length of the array.
That said, 1.2 has been not been used for decades now -- but some very old references might still refer to this behavior.
http://web.archive.org/web/20010408055419/developer.netscape.com/docs/manuals/communicator/jsguide/js1_2.htm
By the coming of ES6, it is recommended to extend array class in the proper way , then , override push method :
class XArray extends Array {
push() {
super.push(...arguments);
return (arguments.length === 1) ? arguments[0] : arguments;
}
}
//---- Application
let list = [1, 3, 7,5];
list = new XArray(...list);
console.log(
'Push one item : ',list.push(4)
);
console.log(
'Push multi-items :', list.push(-9, 2)
);
console.log(
'Check length :' , list.length
)
Method push() returns the last element added, which makes it very inconvenient when creating short functions/reducers. Also, push() - is a rather archaic stuff in JS. On ahother hand we have spread operator [...] which is faster and does what you needs: it exactly returns an array.
// to concat arrays
const a = [1,2,3];
const b = [...a, 4, 5];
console.log(b) // [1, 2, 3, 4, 5];
// to concat and get a length
const arrA = [1,2,3,4,5];
const arrB = [6,7,8];
console.log([0, ...arrA, ...arrB, 9].length); // 10
// to reduce
const arr = ["red", "green", "blue"];
const liArr = arr.reduce( (acc,cur) => [...acc, `<li style='color:${cur}'>${cur}</li>`],[]);
console.log(liArr);
//[ "<li style='color:red'>red</li>",
//"<li style='color:green'>green</li>",
//"<li style='color:blue'>blue</li>" ]
var arr = [];
var element = Math.random();
assert(element === arr[arr.push(element)-1]);
How about doing someArray[someArray.length]={} instead of someArray.push({})? The value of an assignment is the value being assigned.
var someArray = [],
value = "hello world";
function someFunction(value, obj) {
obj["someKey"] = value;
}
someFunction(value, someArray[someArray.length]={});
console.log(someArray)

JS Array.splice return original Array and chain to it

I have a string with values like this a,b,c,d and want to remove a specific letter by index
So here is what I did str.split(',').splice(1,1).toString() and this is (obviously) not working since splice is returning the values removed not the original array
Is there any way to do the above in a one liner?
var str = "a,b,c,d";
console.log(str.split(',').splice(1,1).toString());
Thanks in advance.
You can use filter and add condition as index != 1.
var str = "a,b,c,d";
console.log(str.split(',').filter((x, i) => i != 1).toString());
Another strange solution. Destructure the array, remove the unwanted index, get an object and join the values of it.
var string = "a,b,c,d",
{ 1: _, ...temp } = string.split(',')
console.log(Object.values(temp).join(','));
The alternate way using regex replace
var str = "a,b,c,d";
console.log(str.replace(/,\w+/, ''))
Splice works in place, so oneliner is
const arr = "a,b,c,d".split(','); arr.splice(1,1); console.log(arr.toString());
If you want an string in a oneliner, you have to hardcode the index in a filter
console.log("a,b,c,d".split(',').filter((item, i) => i != 1).toString())
Or two slices (not performant at all)
const arr = "a,b,c,d".split(',')
console.log([...arr.slice(0,1),...arr.slice(2)].toString())

how to convert string values to numbers in a mixed array

I have a mixed array of values all string values. I want to take the string values representing a number and convert them to ints. Here is my array:
const data = 'new york;10.99;2000';
I split it transforming it:
const transData = data.split(';');
transData = ["new york", "10.99", "2000"]
I would like to iterate over that and return two clean int's with a string value for all non number strings. I am a bit stumped. I know this is easy to some but I have tried forEach, for, map, and I still get a NaN value for the first array member. I can't seem to filter or skip it even with an "if" check using for instance:
for(let i=0; i < transData.length; i++)
if(transData[i] != NaN){
transData[i] = + transData[i];
}else{continue};
I know how this works transData[i] = + transData[i];
I just can't seem to automate this thing with iteration/filter/map/whatever..
Any help greatly appreciated. These are baby steps into big boy/girl thinking in javascript.
Here are some of the methods I have tried:
const data = 'new york;10.99;2000';
const transData = data.split(';');
// transData[1] = + transData[1];
// transData[2] = + transData[2];
console.log(transData);
const filteredTransData = transData.filter(data => data > 0);
filteredTransData.forEach((data, idx) => {
filteredTransData[idx] = + filteredTransData[idx];
You can simply use || operater with .map() to get the desired output. As NaN is a falsey value so it would return the string under consideration as it is if it can't be converted to a number by Number:
const data = 'new york;10.99;2000';
const result = data.split(";").map(s => Number(s) || s);
console.log(result);
As pointed by #Maheer Ali:
Above solution has a limitation. It won't convert String "0" to Number 0 as 0 is a falsey value.
So we may use some other solution posted or we may explicitly apply a check for zero (0) where this modified array is being used.
NaN === NaN will always return false. To check if element is NaN you need to use isNaN function.
const transData = ["new york", "10.99", "2000"];
for(let i = 0; i< transData.length; i++){
if(!isNaN(transData[i])){
transData[i] = +transData[i];
}
}
console.log(transData)
Whenever you need to get a new value for each element of array based on previous value its better to use map()
const transData = ["new york", "10.99", "2000"];
const res = transData.map(x => isNaN(x) ? x : +x);
console.log(res)
Try something like this using MAP function
data.split(';').map((x)=>{
x= !isNaN(x)? parseFloat(x):x;
return x;
})
Yes, Maheer Ali's method is good. I just modified all code)
const data = 'new york;10.99;2000;0;-1;-2.45';
let transData = Array
.from(data.split(';'), x => parseFloat(x))
.filter( value => !Number.isNaN(value) );
console.log(transData);
Array.from() - creates a number array from the string array.
Array.filter() - removes NaN from the number array

Javascript - Using condition with object and array

I receive a data value from a API, and I want to make a condition to deal with it. Sometimes it can comes as an array or object. I will use a simple example.
data = [1,2,3] // These values come from API
data.map(i => i++)
The problem is: Sometimes data can also comes as this
data = {
arr: [1,2,3]
}
// It evals an error in .map, because now "data" is an object
I know that I can solve it making something like this:
if(Array.isArray(data))
data.map(i => i++);
else
data.arr.map(i => i++);
But my code is not just a one line .map. Is there a way to make this simple condition without copying and paste code?
Thanks!
You can for example assign the array reference to another variable and use it in the rest of your code, like this:
let arr = Array.isArray(data) ? data : data.arr;
arr.map(i => i++)
A simple OR (||) operator is pretty idiomatic JavaScript:
(data.arr || data).map(i => ++i);
If the data.arr property is defined, that will be mapped, otherwise data itself will be mapped.
Complete snippet:
Note: the post-increment operator would have no effect, so I replaced it with a pre-increment.
let data, result;
data = [1, 2, 3];
result = (data.arr || data).map(i => ++i);
console.log(result);
data = {
arr: [1, 2, 3]
}
result = (data.arr || data).map(i => ++i);
console.log(result);
You can use the ternary operator.
Array.isArray(data)
? data.map(i => i++);
: data.arr.map(i => i++);
You can use destruction es6 , not sure its a good idea but you can achieve your functionality in single line. ;)
let { arr=data } = data;
arr.map(i => i++)
if arr key is not found in data then it will assign default data array.
Cheers
You can do it like this
You can use the ternary operator and assign the value as array directly to temp if it is an Array and if not than you assign using the property like input.arr which is an Array.
So once the value is in form of array than you can use the single map statement so you need not to repeat your map statement.
let data = [1,2,3];
let data1 = {
arr: [1,2,3]
}
function handle(input){
let temp = Array.isArray(input) ? input : input.arr
return temp.map(i => i++);
}
console.log(handle(data))
console.log(handle(data1))
If you don't wish to use an if or a ternary operator you can use Object.values(data).flat() to convert your data into:
[1, 2, 3]
This will essentially not modify your array and leave it be, however, it will compress your data object into an array form.
See working examples below:
Data form 1 (obj):
const data = {arr: [1, 2, 3]};
const res = Object.values(data).flat().map(i => ++i);
console.log(res);
Data form 2 (array):
const data = [1, 2, 3];
const res = Object.values(data).flat().map(i => ++i);
console.log(res);
Do note, however, Object.values does not guarantee order, and thus your array may lose its order. Moreover, if you plan to use this in production .flat() isn't yet supported across all browsers and instead, you may consider looking at a polyfill option

Modify an array without mutation

I am trying to solve a problem which states to remove(delete) the smallest number in an array without the order of the elements to the left of the smallest element getting changed . My code is -:
function removeSmallest(numbers){
var x = Math.min.apply(null,numbers);
var y = numbers.indexOf(x);
numbers.splice(y,1);
return numbers;
}
It is strictly given in the instructions not to mutate the original array/list. But I am getting an error stating that you have mutated original array/list .
How do I remove the error?
Listen Do not use SPLICE here. There is great known mistake rookies and expert do when they use splice and slice interchangeably without keeping the effects in mind.
SPLICE will mutate original array while SLICE will shallow copy the original array and return the portion of array upon given conditions.
Here Slice will create a new array
const slicedArray = numbers.slice()
const result = slicedArray.splice(y,1);
and You get the result without mutating original array.
first create a copy of the array using slice, then splice that
function removeSmallest(numbers){
var x = Math.min.apply(null,numbers);
var y = numbers.indexOf(x);
return numbers.slice().splice(y,1);
}
You can create a shallow copy of the array to avoid mutation.
function removeSmallest(numbers){
const newNumbers = [...numbers];
var x = Math.min.apply(null,newNumbers);
var y = newNumbers.indexOf(x);
newNumbers.splice(y,1);
return newNumbers;
}
array.slice() and [... array] will make a shallow copy of your array object.
"shallow" the word says itself.
in my opinion, for copying your array object the solution is:
var array_copy = copy(array);
// copy function
function copy(object) {
var output, value, key;
output = Array.isArray(object) ? [] : {};
for (key in object) {
value = object[key];
output[key] = (typeof value === "object") ? copy(value) : value;
}
return output;
}
Update
Alternative solution is:-
var arr_copy = JSON.parse(JSON.stringify(arr));
I'm not sure what the exact context of the problem is, but the goal might be to learn to write pure transformations of data, rather than to learn how to copy arrays. If this is the case, using splice after making a throwaway copy of the array might not cut it.
An approach that mutates neither the original array nor a copy of it might look like this: determine the index of the minimum element of an array, then return the concatenation of the two sublists to the right and left of that point:
const minIndex = arr =>
arr.reduce(
(p, c, i) => (p === undefined ? i : c < arr[p] ? i : p),
undefined
);
const removeMin = arr => {
const i = minIndex(arr);
return minIndex === undefined
? arr
: [...arr.slice(0, i), ...arr.slice(i + 1)];
};
console.log(removeMin([1, 5, 6, 0, 11]));
Let's focus on how to avoid mutating. (I hope when you say "remove an error" you don't mean "suppress the error message" or something like that)
There are many different methods on Array.prototype and most don't mutate the array but return a new Array as a result. say .map, .slice, .filter, .reduce
Telling the truth just a few mutate (like .splice)
So depending on what your additional requirements are you may find, say .filter useful
let newArray = oldArray.filter(el => el !== minimalElementValue);
or .map
let newArray = oldArray.map(el => el === minimalElementValue? undefined: el);
For sure, they are not equal but both don't mutate the original variable

Categories

Resources