Error: columnListA[i] is undefined - javascript

When i try to delete some object from columnListA with the objects present in columnListB i'm getting Error: columnListA[i] is undefined
can anyone please tell me some solution for this.
my json list is shown below:
columnListA =[ {id:"a1", value:"XYZ"},{id:"a2", value:"ABC"},{id:"a3", value:"JHI"},{id:"a4", value:"PLM"}]
columnListB =[ {id:"a1", value:"XYZ"}]
My code is this
for ( var j = 0, selLength = columnListB.length; j < selLength; j++)
{
for ( var i = 0, nonSelLength = columnListA.length; i < nonSelLength; i++)
{
if (columnListA[i].id=== columnListB[j].id)
{
columnListA.splice(i, 1);
}
}
}

You're getting this because you're changing columnListA inplace. Since you delete an element, its length passes from 4 to 3, but you still iterate until i = 3.
I suggest creating a new array, instead of changing it inplace and risking this type of error. Example:
columnListA = columnListA.filter(function(nonSel) {
return columnListB.some(function(sel) {
return sel.id !== nonSel.id;
});
});
Array#filter takes a function, and returns a new array that contains only the elements for which the function returns true.
Array#some takes a function, and returns true if the function returns true for all the elements on the array, and false otherwise.

Try:
for ( var j = 0; j < columnListB.length; j++)
{
for ( var i = 0; i < columnListA.length; i++)
{
if (columnListA[i].id === columnListB[j].id)
{
columnListA.splice(i, 1);
}
}
}
JSFiddle
Remove nonSelLength = columnListA.length; i < nonSelLength; from loops and just define variable as less than length of the object

Related

How to add objects into an array without repeating value of one of the properties of objects in JavaScript?

I am trying to insert data into an array. The data is of object form with 2 properties name and value. I am retrieving the data from a different array object with a completely different structure.
The new array that I am creating is as follow:
newarray = [Object, Object, Object]
where Object = {name: "abc", value: "12"}
This is what I am doing for my purpose:
var newarray = [];
for (var i = 0; i < oldarray.length; i++) {
a = newarray.indexOf(oldarray[i].studentname);
if (a == -1) {
newarray.push({
name: oldarray[i].studentname,
value: oldarray[i].marks
})
}
}
I don't want the student name to repeat so I have tried to use indexOf to check the occurrence of the name in the array. But I am not doing it correctly. What am I doing wrong?
var newarray= [];
for(var i=0; i<oldarray.length; i++)
{
var found = false;
for (var j=0; j<newarray.length; j++) {
if (oldarray[i].studentname == newarray[j].studentname) {
found = true;
break;
}
}
if(!found)
{
newarray.push({
name : oldarray[i].studentname,
value :oldarray[i].marks
});
}
}
This code:
a = newarray.indexOf(oldarray[i].studentname);
if (a == -1)
looks to see if the student's name is an entry in the array. But the entries you're putting in the array aren't just namnes, they're objects.
If you want to find if an object with the same name is in the array, you can use Array#some:
if (!newarray.some(function(entry) { return entry.name == oldarray[i].studentname; })) {
// It's not there, add it
}
Array#some calls its callback for each entry. If the callback returns a truthy value for any entry, some stops and returns true; if the callback never returns a truthy value (or the array is empty), some returns false.
It's a bit more concise with ES2015, if you're using ES2015:
if (!newarray.some(entry => entry.name == oldarray[i].studentname)) {
// It's not there, add it
}
== will require that the names be in the same capitalization, of course. If that may not be true, you might want to make both sides lower (or upper) case first.
I don't see a declared anywhere, make sure you're not falling prey to The Horror of Implicit Globals.
var newarray = [];
for (var i = 0; i < oldarray.length; i++) {
a = findWithAttr(newarray, "studentname", oldarray[i].studentname);
if (a == undefined) {
newarray.push({
name: oldarray[i].studentname,
value: oldarray[i].marks
})
}
}
function findWithAttr(array, attr, value) {
for (var i = 0; i < array.length; i += 1) {
if (array[i][attr] === value) {
return i;
}
}
}

Javascript: Simple Function - Uncaught TypeError: Cannot read property 'length' of undefined

I have a function that simply returns the longest property of a given array.
It's a for loop that assigns the looped property to a variable, with the length of the property is longer than that of the variable.
And at last it returns this new variable. But I get an error in line 10, that it can't read the length of undefined.
It seems to have a problem with someArray[i].length inside the for loop.
function longestString(i) {
// i will be an array.
// return the longest string in the array
var someArray = i;
console.log(someArray);
var longestItem = someArray[0];
console.log(longestItem);
for (i = 0; someArray.length; i++) {
if (longestItem.length < someArray[i].length) {
console.log(longestItem);
console.log(someArray[i]);
longestItem = someArray[i];
}
}
document.write(longestItem);
console.log(longestItem);
return longestItem;
}
longestString(['a', 'ab', 'abc']) // should return 'abc'
Any suggestions?
Your for-loop's condition has error.
It should be like given below.
for (i = 0; i < someArray.length; i++)
Check out this fiddle.
Here is the complete code.
function longestString(i) {
// i will be an array.
// return the longest string in the array
var someArray = i;
document.write(someArray); // just testing
var longestItem = someArray[0];
for (i = 0; i < someArray.length; i++) { //Changes in the condition
if (longestItem.length < someArray[i].length) {
longestItem = someArray[i];
}
}
document.write(longestItem);
return longestItem;
}
longestString(['a', 'ab', 'abc']) // should return 'abc'
First of all don't use the same name ifor the function parameter and then in the for loop counter, you may put yourself in really big troubles.
Second thing, your loop doesn't have a stop condition you missed i<someArray.length, it should be like this:
for (i = 0; i<someArray.length; i++) {
if (longestItem.length < someArray[i].length) {
console.log(longestItem);
console.log(someArray[i]);
longestItem = someArray[i];
}
}
Last thing use console.log() or console.dir() to debug/test instead of document.write() because it's a very very bad practice.
There are two errors on your for loop:
You are using an i function parameter which you are using again in your for loop. Try to use a different variable name inside your for loop or at least define the variable with var (to retain the scope), otherwise you will shadow the variable declared as function parameter.
The second one is that you forget to include the test condition into the loop.
function longestString(len) {
// i will be an array.
// return the longest string in the array
var someArray = len;
var longestItem = someArray[0];
var length = someArray.length;
for (var i = 0 ; i < length; i++) {
if (longestItem.length < someArray[i].length) {
longestItem = someArray[i];
}
}
console.log(longestItem);
return longestItem;
}
longestString(['a', 'ab', 'abc']) // should return 'abc'
Maybe there's more than one longest string. I'd suggest looking at the Array instance iteration methods.
var array = ['a', 'abc', 'ab', 'def'];
var maxlen = Math.max.apply(null, array.map(function(string){
return string.length;
}));
var longest = array.filter(function(string){
return string.length === maxlen;
});
var pre = document.createElement('pre');
pre.innerHTML = JSON.stringify(longest);
document.body.appendChild(pre);

Creating a frequency listing of characters

charFreq function that's not quite working out. Hit a wall. I know I may need to
do a conditional. Calling the function returns an Object error. I'm attempting
to get string into an empty object displaying the characters like this - Object
{o: 4, p: 5, z: 2, w: 4, y: 1…}. New to Javascript by the way.
Just realized I shouldn't be appending anything. Do I need to do a .push() to
push the array into the object?
function charFreq (string){
var emptyObj = {};
for(var i = 0; i < string.length; i++) {
// console.log(string.charAt(i));
var args = [string.charAt(i)];
var emptyArr = [''].concat(args);
emptyObj += emptyArr
}
return emptyObj
}
undefined
charFreq('alkdjflkajdsf')
"[object Object],a,l,k,d,j,f,l,k,a,j,d,s,f"
You just need to set emptyObj's key of that specific letter to either 1 if it doesn't exist or increment the count if it already does.
function charFreq(string) {
var obj = {};
for (var i = 0; i < string.length; i++) {
if (!obj.hasOwnProperty(string[i])) {
obj[string[i]] = 1;
} else {
obj[string[i]]++;
}
}
return obj;
}
console.log(charFreq('alkdjflkajdsf'));
Try this instead: you need to create an object property first, then increment it. What you do, is implicitly convert the object to a string and concatenate more string data to it (using += and concat).
This is a simple approach:
function charFreq(string){
var emptyObj={};
for(var i=0; i<string.length; i++) {
if(!emptyObj.hasOwnProperty(string[i])){ // if property doesn’t exist
emptyObj[string[i]]=0; // create it and set to 0
}
emptyObj[string[i]]++; // increment it
}
return emptyObj;
}
A modified version of Richard Kho's code:
function charFreq(string) {
var obj = {};
for (var i = 0; i < string.length; i++) {
var c=string[i];
if (c=='') continue;
if (obj[c]==null) obj[c]=0;
obj[c]++;
}
return obj;
}

Returning a missing element from a string of integers

I'm trying to write a function that accepts an array of unique integers between 0 and 9 (inclusive), and returns the missing element. Here's what I've got. So near but so far.
var currentPlace = 0;
function getMissingElement(superImportantArray){
while (currentPlace < 9){
for (var i = 0; i < 10; i++) {
var arrayNum = superImportantArray[currentPlace]
if (i == arrayNum) {
currentPlace ++;
console.log("so it's not " + i);
}
else if (i !=arrayNum) {
console.log("try..." + i);
}
}
}
}
// run
var myArray = [0,5,1,3,2,9,7,6,4]; // this test should return 8
getMissingElement(myArray);
I'm not sure i'm approaching this correctly. Thanks for your time.
Just wanted to post my answer from the comments. A simpler way to handle this, in my opinion, is to loop over the original array, and flag a new array at the index that they represent. For example, if the number is 4, flag the 4th index in the new array. The reason for all this is because once this is done, one index should be left unflagged. All that would be left to do is find the unflagged index.
Here's an example (I commented the code here, not the fiddle):
function findMissing(array, min, max) {
var missing, unfilledArray, i, j;
// Array to hold the flags
unfilledArray = [];
for (i = min, j = max; i <= j; i++) {
// Flag the index in the new array with the current value
unfilledArray[array[i]] = true;
}
for (i = min, j = max; i <= j; i++) {
// Loop over new array and find the unflagged index
currentUnfilled = unfilledArray[i];
if (!currentUnfilled) {
// Current index not flagged
missing = i;
break;
}
}
return missing;
}
DEMO: http://jsfiddle.net/6GAyw/
The other little feature I added was that you explicitly specify the minimum and maximum value, which, in your case, is 0 and 9. This feature allows this solution to be used on any range of numbers (unlike my original comment/suggestion).
And not that I fully understand big O notation, but I believe this is O(2n), not O(n^2), since there aren't nested loops/indexOf.
If you were looking to get all missing numbers in a range, you can easily modify the function to return an array of unflagged indexes instead. Here's an example:
function findMissing(array, min, max) {
var missing, unfilledArray, i, j;
// Array to hold the missing numbers
missing = [];
// Array to hold the flags
unfilledArray = [];
for (i = min, j = max; i <= j; i++) {
// Flag the index in the new array with the current value
unfilledArray[array[i]] = true;
}
for (i = min, j = max; i <= j; i++) {
// Loop over new array and find the unflagged index
currentUnfilled = unfilledArray[i];
if (!currentUnfilled) {
// Current index not flagged
missing.push(i);
}
}
return missing;
}
DEMO: http://jsfiddle.net/zFS89/
function getMissingElement(superImportantArray){
var result = [], length = Math.max(10, superImportantArray.length);
for (var i = 0; i < length; i++) {
if(superImportantArray.indexOf(i) == -1){
result.push(i);
}
}
return result;
}
Try this. This will return an array of missing elements else return an empty array.
DEMO FIDDLE
So here is one way to do it: Since you know that the array only contains values from 0 to 9, you can build a "set" of numbers and remove each "seen" value in the array from the set:
function getMissingElement(superImportantArray){
var numbers = {};
for (var i = 0; i < 10; i++) {
numbers[i] = true
}
for (var i = 0, l = superImportantArray.length; i < l; i++) {
delete numbers[superImportantArray[i]];
}
return Object.keys(numbers);
}
This would return an array of all numbers that are missing. If there can always only be one missing number you can easily modify this to directly return the number instead.
This should do it.
function getMissingElement(arrayTest) {
// create an array with all digits
var digitsArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var index;
for (var i=0; i<arrayTest.length; i++) {
// get the index of current digit on our array
index = digitsArray.indexOf(arrayTest[i]);
// if found, remove it from our array.
if (index >= 0) {
digitsArray.splice(index,1);
}
}
// the last remaining digit in the original array should be the one missing.
return (digitsArray[0]);
}
This one is better for the eyes.
function getMissingElement(superImportantArray) {
return superImportantArray.reduce(function (sum, value) {return sum - value;}, 45);
}

Create an array and check against it

I am not sure of how to do this, but what I want to do it create an array and be able to add new items to this array. Since the items are supposed to be a random number, when a new instance is created I would like it to be checked against the rest of the array and be sure that the number it has generated is not already in the array. How would I accomplish something like this?
I looked at Šime Vidas's answer and it seems to work, but I tried to shorten it to
var arr = [];
function add(a) {
var n = ~~(Math.random() * 100);
for (var i = 0; i < a.length; i++) {
if ( a[i] === n) { a.push(n) }
}
}
for (var i=0; i<5; i++){
add(arr)
}
document.getElementById('output').innerHTML += arr;
and I don't understand why this wouldn't work. It does pretty much the same thing, correct?
var arr = [];
function add(a) {
var n = ~~(Math.random() * 1000);
!is(a, n) && a.push(n);
}
function is(a, n) {
for (var i = 0; i < a.length; i++) {
if ( a[i] === n ) { return true; }
}
return false;
}
The add function creates a random integer number between 0 and 1000, and adds it to the array.
The is function checks whether the n number is somewhere inside the a array.
Demo: http://jsfiddle.net/kHhMp/2/
Demo 2: http://jsfiddle.net/kHhMp/3/
(Demo 2 shows that a number will only be added to the array if it's not already in it.)
btw
!is(a, n) && a.push(n);
is a short form of this:
if ( is(a, n) == false ) { a.push(n); }
The number is added to the array only if is(a, n) returns false.
UPDATE
var arr = [];
function add(a) {
var n = ~~(Math.random() * 1000),
ok = true;
for (var i = 0; i < a.length; i++) {
if ( a[i] === n ) { ok = false; }
}
ok && a.push(n);
}
If you enjoy fast code and you have many items in your array, you should use an Object rather than an Array.
Instead of doing var my_array=[]; my_array.push(my_number), use var my_object = {}; my_object[my_number] = true to add items in your structure.
With that approach, you can easily check if a new number is already in there with an if (my_object[my_number]) { /* already there */ } else { /* not there yet */ }
Once you're done, you can extract the list of numbers as an array by either using var keys = Object.keys(my_object), or if that's not available, var keys=[],i=0;for (keys[i++] in my_object);, more or less.
You may extend the built in Array object for your needs.
Array.prototype.pushUnique = function(value) {
var len = this.length;
for(var i = 0; i < len; i++) {
if(this[i]===value) return;
}
this.push(value);
}
var uniques = new Array();
uniques.pushUnique(1);
uniques.pushUnique(2);
uniques.pushUnique(1);
// array will contain only 1 and 2
The fastest, most cross-browser way is to iterate over the array using a loop:
var arr = [];
function addNum(num) {
for (i = 0, len = arr.length; i < len; i++) {
if ( arr[i] === num ) { return false; }
}
arr.push(num);
}
Be sure to get the length of the array before you run the loop so the length property isn't constantly checked.
var array = []
array[0] = 'Item'
array[0] === undefined
# returns false
array[1] === undefined
# returns true

Categories