Array.filter numbers plus zero - javascript

I have an easy problem but i'm stuck with it: I would like to transform a list of integers and strings and returns a new list with the strings filtered out :
exemple : ([99,5,'love','hate']) == [99,5]
I used .filter but the zero are filtered as well. What would be the best option?
function filter(l) {
var arr = l.filter(Number);
return arr;
}

You can use .filter() with your own function:
function filter(l) {
var arr = l.filter(function(n) {
return typeof n === "number";
});
return arr;
}
Note that when you use the Number constructor, you'll include numbers and also any value that can successfully be converted to a number. Including such things is a little tricky, since the Number constructor always returns a number. The value might be NaN, but as it happens NaN is in fact a number, despite its intrinsic insistence that it isn't.

Try these helper functions along with Array.filter if you want to strictly filter out only integers:
function isNumber(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
function isInt(n) {
return isNumber(n) && n % 1 === 0;
}
Try these on this fiddle
function isNumber(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
function isInt(n) {
return isNumber(n) && n % 1 === 0;
}
var array = [99,5,'love','hate'];
var result = array.filter(function(x) {
return isInt(x);
});
document.querySelector('#output').innerHTML = JSON.stringify(result, null, 4);
Array: [99,5,'love','hate']
<br/>Result: <pre id="output"></pre>
EDIT: This has a side-effect of string-representation of integers also being returned - so [99,5,'love','hate', '23'] will return [99, 5, '23'] which is probably not what you want.

Related

Polyfill for Array.includes checking NaN

So first off this is not an issue I am facing. I was going through some Javascript blogs when I encountered the Array prototype methods of .indexOf and .includes. So if an array has NaN as a value, then probably indexOf is not going to be able to figure it out and I am left with using .includes. But my question here is, since the browser compatibility of includes actually excludes IE, what should be the alternative to detect the NaN check? I thought of constructing a polyfill by referring this
if (Array.prototype.includes) {
Object.defineProperty(Array.prototype, "includes", {
enumerable: false,
value: function(obj) {
var newArr = this.filter(function(el) {
return el == obj;
});
return newArr.length > 0;
}
});
}
var arr = [NaN];
console.log(arr.includes(NaN));
But unfortunately, it is returning false as well. So what other options do I have? Or am I missing something out?
You can include a polyfill for Number.isNaN as well, and then use it in your filter test - if both the obj and el pass Number.isNaN, then return true:
Number.isNaN = Number.isNaN || function(value) {
return value !== value;
}
// if (!Array.prototype.includes) {
Object.defineProperty(Array.prototype, "includes", {
enumerable: false,
value: function(obj) {
var newArr = this.filter(function(el) {
return el == obj || Number.isNaN(el) && Number.isNaN(obj);
});
return newArr.length > 0;
}
});
// }
var arr = [NaN];
console.log(arr.includes(NaN));
Array#includes uses the Same-Value-Zero algorithm, which is not the same as ==.
Same-Value is provided by Object.is(), and you can manually check for -0 and +0 to get the "-Zero" part of the check.
The linked page includes a polyfill, although since the polyfill includes a step to make -0 and +0 different - which you don't want in a Same-Value-Zero algorithm - you can just leave it out and simplify accordingly:
function SameValueZero(x, y) {
return x === y || (x !== x && y !== y);
}
You can find the index of NaN using firstIndex. try like this.
var arr = [NaN];
let index = arr.findIndex(Number.isNaN)
console.log(index >= 0);

How do I return an array containing the elements which do not match a given parameter in JavaScript?

Write a function called "removeElement".
Given an array of elements, and a "discarder" parameter,
"removeElement" returns an array containing the items in the given
array that do not match the "discarder" parameter.
Notes:
* If all the elements match, it should return an empty array.
* If an empty array is passed in, it should return an empty array.
I thought this would be the solution:
function removeElement(array, discarder) {
var newarr = array.filter(function(cv, i, a){
if (array == []) {
return [];
} else if (cv != discarder ) {
return cv;
}
});
return newarr;
}
But I get this error:
return_an_array_with_all_booleans_not_matching_discarder
return an array with all booleans not matching discarder
I thought this would then work, because initially I didn't add the clause to factor in if all values were equal to discarder.
function removeElement(array, discarder) {
var newarr = array.filter(function(cv, i, a){
if ((array == []) || (cv == discarder)) { // added this expression to evaluate.
return [];
} else if (cv != discarder ) {
return cv;
}
});
return newarr;
}
While Array#filter
The filter() method creates a new array with all elements that pass the test implemented by the provided function.
needs a boolean (or at least a truthy/falsy) value to return, you could just return the check with the given discarder and return the comparison result.
The result is an array without the given value.
function removeElement(array, discarder) {
return array.filter(function(value) {
return value !== discarder;
});
}

How to parse a JSONArray and convert in Javascript

I have a JSONArray in this format:
[
{"COMPLIANCE_ID":"1/FIRST/US/191CC2/20160906/pW1WSpD/1","TOLERANCE":null,"WEIGHTED_ARR_LAST_SLP":"0.03801186624130076","SLIPPAGE_INTERVAL_VWAP_BPS":"10.2711","ROOT_ORDER_ID":"735422197553491","ENTERING_TRADER":"duffy_dma2","SECURITY_ID":"EOG.N","ARRIVAL_MID_PX":"93.6100","WEIGHTED_ARR_SLP":"0.12323190317127024","AVG_PX":"93.6586","ORDER_CCY":"USD","LEAVES_QTY":"0","WEIGHT":"0.02372627566400397","INITIATING_TRADER":null,"PARTICIPATION_RATE":"0E-12","LOCAL_REF_END_TIME":"2016-09-06 06:00:27.775","WEIGHTED_IVWAP_SLP":"0.2436949499725512","NOTIONAL_USD":"477940","LIST_ID":null,"SYM":"EOG","LIQ_CONSUMPTION":"15.21","URGENCY":null,"SIDE":"Sell Short","ALGO":"Hydra","EXECUTING_TRADER":"duffy_dma2","EXEC_QTY":"5103","CL_ORD_ID":"7245294057012908344","LOCAL_REF_START_TIME":"2016-09-06 05:59:57.844","SLIPPAGE_END_LAST_ARR_LAST_BPS":"1.6021","ORD_STATUS":"Filled","IVWAP_PX":"93.5625","LIMIT_PX":"93.6100","ORDER_ID":"735422197553491","VOLUME_LIMIT":"0E-12","SLIPPAGE_ARR_MID_BPS":"5.1939","ORDER_QTY":"5103","CLIENT_ACRONYM":"PEAKM","EXECUTION_STYLE":"2"},{"COMPLIANCE_ID":"1/FIRST/US/191CC2/20160906/pW1PUxP/1","TOLERANCE":null,"WEIGHTED_ARR_LAST_SLP":"-0.046488357264395964","SLIPPAGE_INTERVAL_VWAP_BPS":"0.1625","ROOT_ORDER_ID":"73855219760798","ENTERING_TRADER":"duffy_dma2","SECURITY_ID":"MCD.N","ARRIVAL_MID_PX":"118.0950","WEIGHTED_ARR_SLP":"-0.0041198933937856425","AVG_PX":"118.0923","ORDER_CCY":"USD","LEAVES_QTY":"0","WEIGHT":"0.01830250285999841","INITIATING_TRADER":null,"PARTICIPATION_RATE":"0E-12","LOCAL_REF_END_TIME":"2016-09-06 05:32:24.895","WEIGHTED_IVWAP_SLP":"0.002974156714749742","NOTIONAL_USD":"368684","LIST_ID":null,"SYM":"MCD","LIQ_CONSUMPTION":"62.82","URGENCY":null,"SIDE":"Sell","ALGO":"Hydra","EXECUTING_TRADER":"duffy_dma2","EXEC_QTY":"3122","CL_ORD_ID":"7244573979975932119","LOCAL_REF_START_TIME":"2016-09-06 05:32:19.697","SLIPPAGE_END_LAST_ARR_LAST_BPS":"-2.5400","ORD_STATUS":"Filled","IVWAP_PX":"118.0904","LIMIT_PX":"117.9900","ORDER_ID":"73855219760798","VOLUME_LIMIT":"0E-12","SLIPPAGE_ARR_MID_BPS":"-0.2251","ORDER_QTY":"3122","CLIENT_ACRONYM":"PEAKM","EXECUTION_STYLE":"4"}]
Here all the integers like "93.6585" etc. appear as strings. Is it possible to convert the integers/floats to their originate type (i.e., integer/float)?
Background information: I'm using this JSONArray in Javascript and then want to do sorting on each column, but because those appear as strings, sorting is not happening properly.
This is how I need the json columns in javascript. So, where do I add parseInt or Number for the field ORDER QTY(say)?
In order to convert all numeric values this will suffuce:
var data = [{"COMPLIANCE_ID":"1/FIRST/US/191CC2/20160906/pW1WSpD/1","TOLERANCE":null,"WEIGHTED_ARR_LAST_SLP":"0.03801186624130076","SLIPPAGE_INTERVAL_VWAP_BPS":"10.2711","ROOT_ORDER_ID":"735422197553491","ENTERING_TRADER":"duffy_dma2","SECURITY_ID":"EOG.N","ARRIVAL_MID_PX":"93.6100","WEIGHTED_ARR_SLP":"0.12323190317127024","AVG_PX":"93.6586","ORDER_CCY":"USD","LEAVES_QTY":"0","WEIGHT":"0.02372627566400397","INITIATING_TRADER":null,"PARTICIPATION_RATE":"0E-12","LOCAL_REF_END_TIME":"2016-09-06 06:00:27.775","WEIGHTED_IVWAP_SLP":"0.2436949499725512","NOTIONAL_USD":"477940","LIST_ID":null,"SYM":"EOG","LIQ_CONSUMPTION":"15.21","URGENCY":null,"SIDE":"Sell Short","ALGO":"Hydra","EXECUTING_TRADER":"duffy_dma2","EXEC_QTY":"5103","CL_ORD_ID":"7245294057012908344","LOCAL_REF_START_TIME":"2016-09-06 05:59:57.844","SLIPPAGE_END_LAST_ARR_LAST_BPS":"1.6021","ORD_STATUS":"Filled","IVWAP_PX":"93.5625","LIMIT_PX":"93.6100","ORDER_ID":"735422197553491","VOLUME_LIMIT":"0E-12","SLIPPAGE_ARR_MID_BPS":"5.1939","ORDER_QTY":"5103","CLIENT_ACRONYM":"PEAKM","EXECUTION_STYLE":"2"},{"COMPLIANCE_ID":"1/FIRST/US/191CC2/20160906/pW1PUxP/1","TOLERANCE":null,"WEIGHTED_ARR_LAST_SLP":"-0.046488357264395964","SLIPPAGE_INTERVAL_VWAP_BPS":"0.1625","ROOT_ORDER_ID":"73855219760798","ENTERING_TRADER":"duffy_dma2","SECURITY_ID":"MCD.N","ARRIVAL_MID_PX":"118.0950","WEIGHTED_ARR_SLP":"-0.0041198933937856425","AVG_PX":"118.0923","ORDER_CCY":"USD","LEAVES_QTY":"0","WEIGHT":"0.01830250285999841","INITIATING_TRADER":null,"PARTICIPATION_RATE":"0E-12","LOCAL_REF_END_TIME":"2016-09-06 05:32:24.895","WEIGHTED_IVWAP_SLP":"0.002974156714749742","NOTIONAL_USD":"368684","LIST_ID":null,"SYM":"MCD","LIQ_CONSUMPTION":"62.82","URGENCY":null,"SIDE":"Sell","ALGO":"Hydra","EXECUTING_TRADER":"duffy_dma2","EXEC_QTY":"3122","CL_ORD_ID":"7244573979975932119","LOCAL_REF_START_TIME":"2016-09-06 05:32:19.697","SLIPPAGE_END_LAST_ARR_LAST_BPS":"-2.5400","ORD_STATUS":"Filled","IVWAP_PX":"118.0904","LIMIT_PX":"117.9900","ORDER_ID":"73855219760798","VOLUME_LIMIT":"0E-12","SLIPPAGE_ARR_MID_BPS":"-0.2251","ORDER_QTY":"3122","CLIENT_ACRONYM":"PEAKM","EXECUTION_STYLE":"4"}]
function isNumeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
var parsedData = data.map(function(obj) {
return Object.keys(obj).reduce(function(memo, key) {
var value = obj[key];
memo[key] = isNumeric(value) ? Number(value) : value;
return memo;
}, {})
})
console.log(parsedData);
isNumeric() - The implementation is taken from here because it is a robust way of figuring out if data is numeric or not including detecting negative numbers and floating points, among others.
Alternative one can be used but beware getting false positives or negatives.
Array.map() will iterate through the array and convert each object
Object.keys() extracts all the keys from the object
Array.reduce() finally transforms that array into a new object converting any value it encounters that looks numeric. Note the {} passed at the very end of the call - reduce(func, {}) - that is important, as it's the initial value used for the reduction function.
You can convert strings to integers and floats by doing:
parseFloat("1231.123");
parseInt("12");
Number("123");
Number("123.12");
Sources:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseFloat
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt
Try and run it I am not sure that this is what you want but every value now is changed, and also make some tests my be I had made some mistakes.
var data =[{"COMPLIANCE_ID":"1/FIRST/US/191CC2/20160906/pW1WSpD/1","TOLERANCE":null,"WEIGHTED_ARR_LAST_SLP":"0.03801186624130076","SLIPPAGE_INTERVAL_VWAP_BPS":"10.2711","ROOT_ORDER_ID":"735422197553491","ENTERING_TRADER":"duffy_dma2","SECURITY_ID":"EOG.N","ARRIVAL_MID_PX":"93.6100","WEIGHTED_ARR_SLP":"0.12323190317127024","AVG_PX":"93.6586","ORDER_CCY":"USD","LEAVES_QTY":"0","WEIGHT":"0.02372627566400397","INITIATING_TRADER":null,"PARTICIPATION_RATE":"0E-12","LOCAL_REF_END_TIME":"2016-09-06 06:00:27.775","WEIGHTED_IVWAP_SLP":"0.2436949499725512","NOTIONAL_USD":"477940","LIST_ID":null,"SYM":"EOG","LIQ_CONSUMPTION":"15.21","URGENCY":null,"SIDE":"Sell Short","ALGO":"Hydra","EXECUTING_TRADER":"duffy_dma2","EXEC_QTY":"5103","CL_ORD_ID":"7245294057012908344","LOCAL_REF_START_TIME":"2016-09-06 05:59:57.844","SLIPPAGE_END_LAST_ARR_LAST_BPS":"1.6021","ORD_STATUS":"Filled","IVWAP_PX":"93.5625","LIMIT_PX":"93.6100","ORDER_ID":"735422197553491","VOLUME_LIMIT":"0E-12","SLIPPAGE_ARR_MID_BPS":"5.1939","ORDER_QTY":"5103","CLIENT_ACRONYM":"PEAKM","EXECUTION_STYLE":"2"},{"COMPLIANCE_ID":"1/FIRST/US/191CC2/20160906/pW1PUxP/1","TOLERANCE":null,"WEIGHTED_ARR_LAST_SLP":"-0.046488357264395964","SLIPPAGE_INTERVAL_VWAP_BPS":"0.1625","ROOT_ORDER_ID":"73855219760798","ENTERING_TRADER":"duffy_dma2","SECURITY_ID":"MCD.N","ARRIVAL_MID_PX":"118.0950","WEIGHTED_ARR_SLP":"-0.0041198933937856425","AVG_PX":"118.0923","ORDER_CCY":"USD","LEAVES_QTY":"0","WEIGHT":"0.01830250285999841","INITIATING_TRADER":null,"PARTICIPATION_RATE":"0E-12","LOCAL_REF_END_TIME":"2016-09-06 05:32:24.895","WEIGHTED_IVWAP_SLP":"0.002974156714749742","NOTIONAL_USD":"368684","LIST_ID":null,"SYM":"MCD","LIQ_CONSUMPTION":"62.82","URGENCY":null,"SIDE":"Sell","ALGO":"Hydra","EXECUTING_TRADER":"duffy_dma2","EXEC_QTY":"3122","CL_ORD_ID":"7244573979975932119","LOCAL_REF_START_TIME":"2016-09-06 05:32:19.697","SLIPPAGE_END_LAST_ARR_LAST_BPS":"-2.5400","ORD_STATUS":"Filled","IVWAP_PX":"118.0904","LIMIT_PX":"117.9900","ORDER_ID":"73855219760798","VOLUME_LIMIT":"0E-12","SLIPPAGE_ARR_MID_BPS":"-0.2251","ORDER_QTY":"3122","CLIENT_ACRONYM":"PEAKM","EXECUTION_STYLE":"4"}];
function isInt(n){
if (n === null) return;
n = Number(n);
return !isNaN(n) && n % 1 === 0;
}
function isFloat(n) {
if (n === null) return;
n = Number(n);
return !isNaN(n) && n % 1 !== 0;
}
var result = data.map(function(currVal) {
for (var i = 0, keys = Object.keys(currVal), len = keys.length; i < len; i++) {
var key = keys[i];
var item = currVal[key];
isInt(item) && (currVal[key] = parseInt(item));
isFloat(item) && (currVal[key] = parseFloat(item));
}
return currVal;
});
console.log(result);

Cheking if element is in array js

I am new to JavaScript and i will appreciate some help . I try to search array for element but i cant find the right solution . First i tried this , but no success.
var find = function(string, array) {
for(i=0;i>=array.length-1;i++){
if(array[i]==string){
return true;
}
else{
return false;
}
}
};
Then i tried this
var find = function(string, array) {
if(array.indexOf(string)>-1){
return true;}
else{
return false;
}
};
but it doesn't work with numbers
This are my tests
Test.assertEquals(find("hello", ["bye bye","hello"]), true);
Test.assertEquals(find("2", ["bye bye","2"]), true);
Test.assertEquals(find("2", ["bye bye",2]), false);
You are returning false the first time an element is found that doesn't match what you are looking for. You should only return false once the entire array has been processed. Your loop is also incorrect, if i is 0, it will never be greater than or equal to the array length unless the array is empty:
var find = function(string, array) {
for(i=0; i < array.length; i++) {
if(array[i]==string) {
return true;
}
}
return false;
};
You should also focus on naming conventions. Your function is called find, but it doesn't actually return the found element. I would name the function contains.
This is a good learning exercise, but don't reinvent the wheel:
[1,2,3,4,5,6].indexOf(foo) > -1
This will return true if foo is in the array.
Assuming you have a Test.assetEquals Function just use the build in array function:
Test.assertEquals((["bye bye","hello"].indexOf('hello') > -1),true);
With type conversion:
var a = [1, 2, 3];
if (a.some(function (x) { return x == "2" })) {
...
}
Strict comparison:
if (a.indexOf("2") >= 0) {
...
}

is this valid JavaScript arrays comparing algorithm?

Primordial topic, I know, but can anyone please comment on the following algorithm for comparing two ES5 arrrays:
function equal_arrays(a, b) {
"use strict";
var c = 0;
return a.every(function (e) {
return e === b[c++];
});
}
I think this is very clean and obvious use of [].every(), to quickly compare two arrays?
I have that nagging "surely it can not be that simple ?" feeling about it ?
NOTE: two arrays are equal when they contain all elements in the same position strictly equal to each other. So both the element index and element value have to be exactly equal. Values of different types are considered not equal. Sparse arrays are also compared.
TEST CASES:
equal_arrays([],[]) ; // => true
equal_arrays([1,2],[1,2]) ; // => true
equal_arrays([1,,2],[1,,2]) ; // => true
equal_arrays([,],[,]); // => true
equal_arrays([1,,3,,,],[1,,3,,,]); // => true
Uses cases yielding => false, one can imagine herself. Comparing non-arrays is a syntax error.
Many thanks to the well meaning and helpful contributors. It appears that the "best" (there is never such a thing) implementation is this:
function has(element, index)
{
return this[index] === element;
}
function equal_arrays(a, b)
{
return (a.length === b.length) && a.every(has, b) && b.every(has, a);
}
#tom's implementation of the two-way every() which is necessary sp that test cases like this one work:
equal_arrays([1,,3],[1,2,3]); //=> false
Once again thanks ...
No, it is not valid. From the MDN docs:
callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.
So if the first array has 'gaps' they will be skipped over.
equal_arrays([1, 2, , 4], [1, 2, 4]); // true
equal_arrays([1, 2, 4], [1, 2, , 4]); // false
Here is a better implementation:
function equal_arrays(a, b) {
if (a.length != b.length) return false;
var i;
for (i = 0; i < a.length; i++) {
if (a[i] !== b[i]) return false;
}
return true;
}
Here is an elegant implementation of #RobG's two-way every() idea:
function has(element, index)
{
return this[index] === element;
}
function equal_arrays(a, b)
{
return (a.length === b.length) && a.every(has, b) && b.every(has, a);
}
I have that nagging "surely it can not be that simple ?" feeling about it ?
No, it isn't. Using every on one array will test it for every member of that array but not the other. You have to test both ways.
Also, it depends on your criteria for "equal". You might want every member of the same index to have the same value, but you might not be concerned about order so is [1,2] equal to [2,1]? and is [,,,2] equal to [2]?
Also, should [1,,2] equal [1,undefined,2], i.e. should a member that doesn't exist be "equal" to one that does but has the value undefined?
An array comparison function
The following may do the job. It compares both ways, checking own properties and values. I think it covers all cases but am willing to be convinced otherwise. Might be better as a separate function, but adding to Array.prototype is convenient.
// Test that own properties of two arrays have the same values
Array.prototype.isEqualTo = function(a) {
var visited = {};
if (this.length != a.length) return false;
// Test every own property of this, remember tested properties
for (var p in this) {
if (this.hasOwnProperty(p)) {
visited[p] = p;
if (!(a.hasOwnProperty(p)) || this[p] !== a[p]) {
return false;
}
}
}
// Reverse test that comparison array only has tested properties
for (var q in a) {
if (a.hasOwnProperty(q) && !(q in this)) {
return false;
}
}
return true;
}
console.log([1,,2].isEqualTo([1,undefined,2])); // false, not defined != undefined
console.log([1,,2].isEqualTo([1,2])); // false, different length
console.log([1,2].isEqualTo([1,2])); // true
Note that inherited properties should be ignored as if arrays from different windows are compared (e.g. one is from a frame) then inherited properties won't be equal.
As an alternative, if you just want to check if both arrays are exactly the same you could just do this:
var a = [1,2,3,4];
var b = [1,2,3,4];
JSON.stringify(a) == JSON.stringify(b); //= true
That should work with arrays of numbers and strings.
As CrazyTrain said, the increment value is useless and you need to check for length first:
function equalArrays( a, b ) {
"use strict";
if (a.length !== b.length) return false;
return a.filter(function(el){ return el;}).every(function(e, i) {
return e === b[i];
});
}
Is a valid algorithm to compare arrays by value.

Categories

Resources