JavaScript looping through an array to check for numeric values - javascript

I have an an array that returns the values such as the following:
//Eg 1 [ [ "214323", "34243" ], [ "3333", "123" ] ]
//Eg 2 [ [ "214323" ],[ "3333" ] ]
I want to validate if the array holds only numbers with no spaces or null, else I would like to throw an error.
This is my following code and it does not work in the above example. It throws out an error even though all values are numeric.
for (var i = 0; i <= arrayVals.length; i++) {
if(!(/^\d+$/.test(arrayVals[i]))) {
err_comp=true;
}
}
if( err_comp ==true) {
alert( 'The value has to be only numeric.');
}

You have an array of arrays, thus you need two loops:
var err_comp = false;
for (var i = 0; i < arrayVals.length; i++) {
var arr = arrayVals[i];
for (var j = 0; j < arr.length; j++) {
if (!(/^\d+$/.test(arr[j]))) {
err_comp = true;
}
}
}
Otherwise, you'd be testing /^\d+$/.test([ "214323", "34243" ]).

you should not use <= because you start with 0 you should use <:
for (var i = 0; i < arrayVals.length;

multi_arr.every(function(arr) {
return arr.every(function(n) {
return /^\d+$/.test(n);
});
});
You can change the test as you need, and you can add a .every patch for IE8 if you want.
And you can make reusable your functions.
function forEveryArray(fn) {
return function every_array(arr) {
return arr.every(fn)
}
}
function isNumber(n) { return /^\d+$/.test(n); }
multi_arr.every(forEveryArray(isNumber));

Related

JavaScript: transform a string to json with some rules

I need to write a function which can transform the following data (input string) to a json.
data:
AA,BB
,CC
,,DD
,EE
JSON:
{
"AA": [
{
"BB": []
},
{
"CC": [
{
"DD": []
}
]
},
{
"EE": []
}
]
}
AA, BB, CC ... can any string and the data is input as a string.
I write a part of the function (see the following codes) and have no more good idea.
function str2json(str) {
var lines = str.split("\n");
var arr = new Array();
for (let i = 0; i < lines.length; i++)
{
var objs = lines[i].split(",");
arr.push(objs);
}
for (let i=0; i < arr.length; i++)
{
for (let j=0; j < arr[i].length; j++)
{
if(arr[i][j].length === 0)
{
arr[i][j] = arr[i-1][j];
}
else
{
break;
}
}
}
// TODO
}
I just transform the data into an array then add right data into null, the result is:
AA,BB
AA,CC
AA,CC,EE
AA,FF
Then I thought of using a loop to create an object then use JSON.stringify(object).
How can I continue or redo it?
Thanks!
You could take a helper array for all last levels and pick the result from the first element.
This works because you take after splitting an empty string as flag for taking the last array for inserting a new object.
var data = 'AA,BB\n,CC\n,,DD\n,EE',
result = [],
levels = [result];
data
.split('\n')
.forEach(s => s
.split(',')
.forEach((v, i) => {
if (!v) return;
levels[i].push({ [v]: (levels[i + 1] = []) });
})
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

I keep getting cannot read property error

I am trying to do a bubblesort. I am using this algorithm to sort a 2d array and I keep getting an error. Here is the function:
var array = [
[ "Rober Hill" , 123.54 ],
[ "Chrsitopher Reddkin", 54.67 ],
[ "Maggie Woods" , 1000.87 ],
[ "Jennifer Jones" , 3.34 ],
[ "Marcus Parker" , 64.98 ]
];
table = document.getElementById("table");
function bubbleSort(array, length, element)
{
var swapped = false;
do
{
for (var a = 0; a < 5; a++) // Line 59
{
if (array[a][1] > array[a+1][1])
{
var temp = array[a][1];
array[a][1] = array[a+1][1];
array[a+1][1] = temp;
swapped = true;
}
}
} while(swapped);
return array;
}
The error says: Sorting.html:59 Uncaught TypeError: Cannot read property '0' of undefined. I have this function on a button. Any kind of help would be nice! Thank you
Running your code exactly as it is, I get:
Cannot read property '1' of undefined
This is because in your comparison, you're attempting to compare array[a][1] > array[a+1][1], and this works except for the last loop, where array[a+1] doesn't exist, and because it doesn't exist, 1 is undefined.
Here's a working solution, with a few notable differences.
I don't know why you had length, and element as parameters for your bubbleSort, but they're gone now
You can just use the array length in your for loop, that way if you add more items to your array, you don't have to update the 5 you had hardcoded.
In the for loop, I minus 1 from the array length so we're never trying to compare the last item against an item after it that doesn't exist.
Also, I used i instead of a, since that's a common variable name for an incrementer.
I defined swapped inside the do...while, otherwise you'll have created an infinite loop because swapped will get set to true on the first pass and stay true forever.
You don't have to return the array, as it is modifying the original in place when you call bubbleSort
var array = [
["Rober Hill", 123.54],
["Chrsitopher Reddkin", 54.67],
["Maggie Woods", 1000.87],
["Jennifer Jones", 3.34],
["Marcus Parker", 64.98]
];
function bubbleSort(array) {
do {
var swapped = false;
for (var i = 0; i < array.length - 1; i++) {
if (array[i][1] > array[i + 1][1]) {
var temp = array[i];
array[i] = array[i + 1];
array[i + 1] = temp;
swapped = true;
}
}
} while (swapped);
}
bubbleSort(array)
console.log(array);
Move var swapped = false; inside do {....
Also update condition in for it should be like a < 4; or it's better if you use generalized condition as a < array.length - 1;
var array = [
["Rober Hill", 123.54],
["Chrsitopher Reddkin", 54.67],
["Maggie Woods", 1000.87],
["Jennifer Jones", 3.34],
["Marcus Parker", 64.98]
];
function bubbleSort(array, length, element) {
do {
var swapped = false;
for (var a = 0; a < array.length - 1; a++) // Line 59
{
if (array[a][1] > array[a + 1][1]) {
var temp = array[a][1];
array[a][1] = array[a + 1][1];
array[a + 1][1] = temp;
swapped = true;
}
}
} while (swapped);
return array;
}
console.log(bubbleSort(array));

Compare string to array of object

I come up with this solution to compare a string to an array of object. However, I don't think this is the best solution. Any suggestion on how to make this function perform better for large array of object?
var a = "blAh";
var b = [{
"tag": "tag1",
"icons": ["blah"]
}, {
"tag": "tag2",
"icons": ["Blah", "apple", "banana", "bLaH"]
}];
// Desired output "tag1, tag2"
function getTitle(tags, icon) {
let arr = [];
for (var i = 0; i < tags.length; i++) {
tags[i].icons.forEach(elem => {
if (icon.toLowerCase() === elem.toLowerCase()) {
if (!arr.includes(tags[i].tag)) {
arr.push(tags[i].tag);
}
}
});
}
return arr.join(', ');
}
console.log(getTitle(b, a));
for readability, I would use the following :
var res = b.filter(el =>
el.icons.length < 0
? false
: el.icons.map(icon => icon.toLowerCase()).indexOf(a.toLocaleLowerCase()) != -1
).map(el => el.tag).join(', ');
But for performances, this one would be better :
var res = [];
var i, j;
for (i = 0; i < b.length; i++) {
if (b[i].icons.length < 0) {
} else {
for (j = 0; j < b[i].icons.length; j++)
b[i].icons[j] = b[i].icons[j].toLowerCase();
if (b[i].icons.indexOf(a.toLocaleLowerCase()) !== -1)
res.push(b[i].tag);
}
}
res = res.join(', ');
Here is why :
indexOf is always faster than includes (or equal in old versions of chrome). benchmark
for loops are always faster than array methods like filter, map or reduce. benchmarks : map, filter
Also it's intresting to see that for loops are faster than indexOf in the latest version of chrome (60)
Hope it helps,
Best regards

Javascript find and count duplicate key values

I have a JSON array as follows:
var testJSON = [
{ "AssetA": "asset_a", "AssetB": "asset_b" },
{ "AssetA": "asset_a", "AssetB": "asset_b" },
{ "AssetA": "asset_c", "AssetB": "asset_d" },
{ "AssetA": "asset_c", "AssetB": "asset_e" }];
What I'd like to do is count all the duplicates. For example, I'd like my result to be another array, where the first two elements of the row are are the repeating values, and the third element is the number of times it repeats like so:
[{asset_a, asset_b,2},
{asset_c, asset_d,1},
{asset_c, asset_e,1}]
Here is what I have so far to be able to identify the duplicates, but it keeps getting hung up and my visual studio crashes:
for (var i = 0; i < testJSON.length; i++) {
for (var j = i + 1; j < testJSON.length;) {
if (testJSON[i][0] == testJSON[j][0] && testJSON[i][1] == testJSON[j][1])
// Found the same. Remove it.
console.log("they are equal");
else
// No match. Go ahead.
j++;
}
}
You could use an object for collecting and an array for the result set
Both properties are used as key and used for lookup in the array. If not found, the a new array is build with the needed values and inserted into the result set. Then the count gets increased.
var testJSON = [{ "AssetA": "asset_a", "AssetB": "asset_b" }, { "AssetA": "asset_a", "AssetB": "asset_b" }, { "AssetA": "asset_c", "AssetB": "asset_d" }, { "AssetA": "asset_c", "AssetB": "asset_e" }],
result = [];
testJSON.forEach(function (a) {
var k = a.AssetA + '|' + a.AssetB;
if (!this[k]) {
this[k] = [a.AssetA, a.AssetB, 0];
result.push(this[k]);
}
this[k][2]++;
}, Object.create(null));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
testJSON[i][0]
I do not believe this will work like that. What you have is an ARRAY of OBJECTS.
Therefore, testJSON[i] will return an OBJECT, not an ARRAY, therefore testJSON[i][0] shouldn't return anything valuable. What you want is testJSON[i]['AssetA']
Hangup
Another thing is when if (testJSON[i][0] == testJSON[j][0] && testJSON[i][1] == testJSON[j][1]) succeds on j = i+1. In this case, you will just keep iterating on the same value of j. You need to add j++ to your forloop and delete the else clause, or handle it otherwise for desired effect.
For example
for (var i = 0; i < testJSON.length; i++) {
for (var j = i + 1; j < testJSON.length; j++) {
if (testJSON[i]["AssetA"] == testJSON[j]["AssetA"] &&
testJSON[i]["AssetB"] == testJSON[j]["AssetB"])
console.log("they are equal");
}
}

Add or remove element(s) to array

I have an existing array of objects :
existingArray = [
{object1: 'object1'},
{object2: 'object2'}
{object3: 'object3'},
]
I receive a new one :
newArray = [
{object2: 'object2'},
{object3: 'object3'},
{object4: 'object4'}
]
I want only to modify the existing one to get the new one as the result (push+splice)
Here is what I have for now (is there a better way ?)
for (var i = 0; i < newArray.length; i++) {
// loop first to push new elements
var responseToTxt = JSON.stringify(newArray[i]);
var newStatement = false;
for(var j = 0; j < existingArray.length; j++){
var statementToTxt = JSON.stringify(existingArray[j]);
if(statementToTxt === responseToTxt && !newStatement){
newStatement = true;
}
}
if(!newStatement){
statements.push(response[i]);
}
}
var statementsToSplice = [];
for (var i = 0; i < existingArray.length; i++) {
// then loop a second time to split elements not anymore on the new array
var statementToTxt = JSON.stringify(existingArray[i]);
var elementPresent = false;
var element = false;
for(var j = 0; j < newArray.length; j++){
var responseToTxt = JSON.stringify(newArray[j]);
if(responseToTxt === statementToTxt && !elementPresent){
elementPresent = true;
} else {
element = i;
}
}
if(!elementPresent){
statementsToSplice.push(element);
}
}
Then I needed to split multiple times in the array :
existingArray = statementsToSplice.reduceRight(function (arr, it) {
arr.splice(it, 1);
return arr;
}, existingArray.sort(function (a, b) { return b - a }));
Here is the example :
https://jsfiddle.net/docmz22b/
So the final output should always be the new array, but only by push or splice the old one.
In this case, the final outpout will be
existingArray = [
{object2: 'object2'},
{object3: 'object3'}
{object4: 'object4'},
]
The new array could contains multiple new elements and/or deleted elements that is currently in the existingArray
Use shift() and push()
existingArray.shift(); //Removes the first element of the array
existingArray.push({'object4' : 'object4'});
Fiddle
I'm almost 100% sure that there is a better way to do it, but at least this works, feel free to comment any suggestions / optimizations.
existingArray = [
{object1: 'object1'},
{object2: 'object2'},
{object3: 'object3'}
];
newArray = [
{object2: 'object2'},
{object3: 'object3'},
{object4: 'object4'}
];
// Loop all the old values, if is not in the new array, remove it
existingArray.forEach(function(item) {
if(!inArray(item, newArray)) {
var idx = indexOfObjectInArray(item, existingArray);
existingArray.splice(idx, 1);
}
});
// Loop all the new values, if is not in the new array, push it
newArray.forEach(function(item) {
if (!inArray(item, existingArray)) {
existingArray.push(item);
}
});
// Auxiliar functions
function inArray(initialValue, array) {
testValue = JSON.stringify(initialValue);
return array.some(function(item) {
return testValue == JSON.stringify(item);
});
}
function indexOfObjectInArray(initialValue, array) {
var result = -1;
testValue = JSON.stringify(initialValue);
array.forEach(function(item, idx) {
if (testValue == JSON.stringify(item)) {
result = idx;
};
});
return result;
}
Maybe this helps. It features Array.prototype.forEach and Array.prototype.some.
Splice unwanted items
Look if object with same property exist
If yes, then assign new object
Else push the object
var existingArray = [
{ object1: 'object1' },
{ object2: 'object2' },
{ object3: 'object3' },
],
newArray = [
{ object2: 'object22' },
{ object3: 'object33' },
{ object4: 'object44' }
];
function update(base, change) {
var changeKeys = change.map(function (a) { return Object.keys(a)[0]; }),
i = 0;
while (i < base.length) {
if (!~changeKeys.indexOf(Object.keys(base[i])[0])) {
base.splice(i, 1);
continue;
}
i++;
}
change.forEach(function (a) {
var aKey = Object.keys(a)[0];
!base.some(function (b, i, bb) {
if (aKey === Object.keys(b)[0]) {
bb[i] = a; // if that does not work, use bb.splice(i, 1, a);
return true;
}
}) && base.push(a);
});
}
update(existingArray, newArray);
document.write('<pre>' + JSON.stringify(existingArray, 0, 4) + '</pre>');

Categories

Resources