Related
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));
I have an an array which is mentioned below. I would like to remove an item from the array which has empty property value using JavaScript.
Actual array:
[
{
"href":"/client",
"methods":[]
},
{
"href":"/home",
"methods":
{
"type1":"GET",
"type2":"POST",
}
},
{
"href":"/about",
"methods":[]
},
{
"href":"/contact",
"methods":
{
"type1":"GET",
"type2":"POST",
}
}
]
Expecting result:
[
{
"href":"/home",
"methods":
{
"type1":"GET",
"type2":"POST",
}
},
{
"href":"/contact",
"methods":
{
"type1":"GET",
"type2":"POST",
}
}
]
This is the job for filter. however filter does not modify the existing array so you need to assign it to a different array/overwrite the current variable
a = a.filter(item => Object.keys(item.methods).length > 0)
Iterate over the object array and filter based on methods property length.
var obj = [...];
obj = obj.filter((val) => val.methods && val.methods.length !== 0);
In the case of methods, you can easily walk the object and then call delete on the keys with values that are empty.... or empty arrays. I expanded the answer to cover not only keys of methods where an array is empty, but all keys with what i would define as empty contents.
var l = [];
for (var i = 0; i < l.length; i++){
var keys = Object.keys(l[i]);
for ( var j = 0; j < keys.length; j++){
var value = keys[j];
// In your use case, you are only doing arrays so i coded it as such.
if (value.length == 0){
delete l[i][j];
}
}
}
If you want to expand it to cover a variety of cases such as empty string, empty arrays, empty maps, or null values you can defined a function to do that.
function isValueDeletable(value){
if (value == null) return true;
if (value == "") return true;
if (value instanceof Array && value.length == 0) return true;
if (value instanceof Map && Object.keys(value).length == 0) return true;
return false;
}
and apply that instead of the value.length == 0;
if (isValueDeletable(value)){ delete l[i][j]; }
Then l is modified to remove all keys with empty values.
enter var json = {};
var key = "giveitakeyvalue";
json[key] = null;
delete json[key];
I have an array and I want to remove all the string elements from it.
This is what I have so far. The result is not what I want since it returns only "bicycle"
Also, I am doing this in Test Complete so I need to have a main function that logs the result.
function ex06(){
var mailBox = "mailbox";
var twenty = 20;
var isItRaining = true;
var goat = "";
var stringsArray = ["bicycle", "pocket", 3, mailBox, twenty, isItRaining, goat];
var result = removeStrings();
Log.Message("stringsArray looks like this after the removal of all the string elements: " + result);
function removeStrings(){
var i;
var x
for(i = 0; i < stringsArray.length; i++){
if (typeof(stringsArray[i]) === 'string'){
x = stringsArray.splice(i, 1);
return x;
}
}
}
}
Version 1, with Array#filter
var a = [1, 2, "3", "4", true];
a = a.filter(function (e) {
return typeof e !== 'string';
});
document.write('<pre>' + JSON.stringify(a, 0, 4) + '</pre>');
Version 2, with Array#splice and running backwards.
var a = [1, 2, "3", "4", true],
i = a.length;
while (i--) {
if (typeof a[i] === 'string') {
a.splice(i, 1);
}
}
document.write('<pre>' + JSON.stringify(a, 0, 4) + '</pre>');
The Array.prototype.filter method is what you need:
var stringsArray = ["bicycle", "pocket", 3, mailBox, twenty, isItRaining, goat];
var result = stringsArray.filter(function(element) {
return typeof element !== 'string';
});
you need to reduce the counter variable and check the original array
try this simple example
var a = [1,2,"3", "4", true];
for( var counter = 0; counter < a.length; counter++)
{
if ( (typeof a[ counter ] ) == "string" )
{
a.splice(counter,1); counter--;
}
}
console.log(a); //output [1, 2, true]
try this code:
function ex06(){
var mailBox = "mailbox";
var twenty = 20;
var isItRaining = true;
var goat = "";
var stringsArray = ["bicycle", "pocket", 3, mailBox, twenty, isItRaining, goat];
var result = removeStrings();
Log.Message("stringsArray looks like this after the removal of all the string elements: " + result);
function removeStrings(){
var newarray = [];
var i;
var x
for(i = 0; i < stringsArray.length; i++){
if (typeof(stringsArray[i]) !== 'string'){
newarray.push(stringsArray[i]);
}
}
return newarray
}
}
JavaScript offers native methods to filter arrays, so that you can remove string elements more easily: Array.prototype.filter can make the process a lot easier (and prevents strange behaviours when using splice inside a loop).
function ex06(){
var mailBox = "mailbox";
var twenty = 20;
var isItRaining = true;
var goat = "";
var stringsArray = ["bicycle", "pocket", 3, mailBox, twenty, isItRaining, goat];
var result = removeStrings(stringsArray);
Log.Message("stringsArray looks like this after the removal of all the string elements: " + result);
function removeStrings(arrayWithString){
return arrayWithString.filter(function(item) {
return typeof item !== 'string'; // returns only items which are not strings
});
}
}
A small piece of advice: Pass in the array into your function instead of referencing it from the parent scope. This way you have a pure, reusable function (and no strange side effects you might not want).
I assume this is an exercise, and that's why you're not using Array#filter.
The problem is that you have your return x inside your for loop, so you return the first string you find.
You have at least three options:
Don't return anything, since removeStrings is modifying the original array. That one's easy: Just remove the return x; line.
Don't modify the original array; instead, create and return a new array with the strings left out. In that case, you'd start with x = [] before the loop, remove the splice call, and instead push any non-string onto x.
Modify the original array, and create and return a new array containing the strings you've removed. In that case, you'd remove return x from inside the loop, have x = [] before the loop, and push the entries you remove onto x. Then return x at the end.
In any of the places where you're modifying the original, note gurvinder372's point that when you remove an entry, you need to not increase the index counter, as you'll end up skipping the next entry.
I wouldn't do it the way he suggests, though; when I'm looping through an array modifying it, for isn't what I reach for, I reach for while:
i = 0;
while (i < stringsArray.length) {
if (typeof stringsArray[i] === 'string'){
stringsArray.splice(i, 1);
// We leave `i` alone here, because we need to process
// the new `stringsArray[i]` on the next pass
} else {
// Didn't remove this entry, move past it
++i;
}
}
Side note: typeof isn't a function, it's an operator, there's no need to put its operand in ():if (typeof stringsArray[i] === 'string'){
Its a very small issue and for the life of me I can't figure out what it is. My brain has locked itself from thinking. I need someone else to have a look this code.
The output of the code should be: [1,0,0,0]
UPDATE:
The function should be able to read an array of numbers and if it finds any zeros within the array it should move them to the end of the array.
The output of the code keeps coming as: [0,1,0,0]
var arrNum = [0,0,0,1];
function test() {
for(var i=0; i<arrNum.length; i++){
if(arrNum[i] == 0){
arrNum.splice(i,1)
arrNum.splice(arrNum.length, 1, 0)
}
}
return alert(arrNum)
}
Here is a working plunker.
Apologies for this, I know the issue is something very small but my brain has stopped working now and I need a fresh pair of eyes.
With the way you have it written, you need to loop in the reverse order. You end up skipping indexes when you remove the index. Looping in the reverse direction keeps you from skipping them.
for(var i=arrNum.length-1; i>=0; i--){
You can use unshift() to insert at beginning of an array and push() to the end...
var arrNum = [0,0,0,1];
var output = [];
function test()
{
for(var i=0; i<arrNum.length; i++)
{
if(arrNum[i] == 0)
output.push(0);
else
output.unshift(arrNum[i]);
}
return alert(output)
}
var arrNum = [0,0,0,1];
var result = [];
arrNum.forEach(function(v) {
!!v ? result.unshift(v) : result.push(v);
});
console.log(result);
You are iterating with index i = 0,1,2,3 and at the same time removing first elements of array. So your iteration can not see the 1, it jumps over as it is moved to already iterated index. Easiest would be to just reverse the loop to bypass the issue.
var arrNum = [0,0,0,1];
function test() {
for(var i= arrNum.length; i >= 0; i--){
if(arrNum[i] == 0){
arrNum.splice(i,1)
arrNum.splice(arrNum.length, 1, 0)
}
}
return alert(arrNum)
}
Prefer built-in functions every time possible.
var output = [];
[0,0,0,1].forEach(function(num) {
if(num == 0) output.push(0);
else output.unshift(num)
})
Why don't you use a temporary array to help? The problem with your code is that the splice() function modifies the original array, and you are doing it inside the loop.
The code below produces what you need:
var arrNum = [0,0,0,1];
var arrResult = new Array();
function test() {
for(var i=arrNum.length-1; i>=0; i--)
{
arrResult.push(arrNum[i]);
}
arrNum = arrResult;
return alert(arrNum);
}
With another array to store the new values, you gain flexibility to do whatever you need with the data of the first array.
A nice little way using Objects - busy learning them so just posting a variation of deligation
var methods = {
moveZero: function(arr){
//console.log(arr);
var newArr = [];
for(var i = 0; i < arr.length; i++){
if(arr[i] === 0){
newArr.push(arr[i]);
}else{
newArr.unshift(arr[i]);
}
}
console.log(newArr);
}
}
var arrNum = Object.create(methods);
arrNum.moveZero([0,0,50,56,85,0,0,43,10,0,1]);
JSFiddle - https://jsfiddle.net/ToreanJoel/qh0xztgc/1/
The problem was you are modifying an array while looping over it in if statement.
Here is a working plunker of your example.
var len = arrNum.length;
var index = 0;
while(len) {
if(arrNum[index] == 0) {
arrNum.splice(index,1);
arrNum.push(0);
} else {
++index;
}
--len;
}
As the operation you want to do is actually sorting, for readability and compactness of code maybe you should be doing this instead:
var arrNum = [0,1,0,0];
arrNum.sort(function(a, b) {
return a == 0 ? 1 : 0;
});
It can contain any number and will keep order of others than 0
Ok, this might be easy for some genius out there but I'm struggling...
This is for a project I'm working on with a slider, I want an array the slider can use for snap points/increments... I'm probably going about this in a mental way but its all good practice! Please help.
var frootVals = [1,2,3,4,5];
var frootInc = [];
for (i=0; i<=frootVals.length; i++) {
if (i == 0){
frootInc.push(frootVals[i]);
}
else{
frootInc.push(frootInc[i-1] += frootVals[i])
}
};
What I'm trying to do is create the new array so that its values are totals of the array elements in frootVals.
The result I'm looking for would be this:
fruitInc = [1,3,6,10,15]
For a different take, I like the functional approach:
var frootVals = [1,2,3,4,5];
var frootInc = [];
var acc = 0;
frootVals.forEach(function(i) {
acc = acc + i;
frootInc.push(acc);
});
var frootVals = [1,2,3,4,5]
, frootInc = [];
// while i < length, <= will give us NaN for last iteration
for ( i = 0; i < frootVals.length; i++) {
if (i == 0) {
frootInc.push(frootVals[i]);
} else {
// rather than frootIne[ i-1 ] += ,
// we will just add both integers and push the value
frootInc.push( frootInc[ i-1 ] + frootVals[ i ] )
}
};
There were a few things wrong with your code check out the commenting in my code example. Hope it helps,
This will do:
var frootVals = [1,2,3,4,5];
var frootInc = [];
for (i=0; i < frootVals.length; i++) { // inferior to the length of the array to avoid iterating 6 times
if (i == 0) {
frootInc.push(frootVals[i]);
}
else {
frootInc.push(frootInc[i-1] + frootVals[i]) // we add the value, we don't reassign values
}
};
alert(JSON.stringify(frootInc));
jsfiddle here: http://jsfiddle.net/f01yceo4/
change your code to:
var frootVals = [1,2,3,4,5];
var frootInc = [frootvals[0]]; //array with first item of 'frootVals' array
for (i=1; i<frootVals.length; i++) {
frootInc.push(frootInc[i-1] + frootVals[i]); //remove '='
}
Here's a very simple pure functional approach (no vars, side-effects, or closures needed):
[1,2,3,4,5].map(function(a){return this[0]+=a;}, [0]);
// == [1, 3, 6, 10, 15]
if you name and un-sandwich the function, you can use it over and over again, unlike a hard-coded var name, property name, or for-loop...