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));
Related
I'm trying to compare for some duplicate value inside a loop because I need to do some logic. My problem is that I can't get the output that I expected.
var tempVal;
for (i = 0; i < obj.length; i++) {
var items = obj[i];
tempVal = items.fund;
console.log(tempVal);
console.log(tempVal == tempVal);
if(tempVal == tempVal){
//do something
}
In my example I have 2 same value in tempVal variable. My console.log(tempVal == tempVal) returns true in first loop but I thought it would return null or undefined in first loop because there's nothing to compare because it's empty on the first loop. What I need is top first return false then true. Thanks
You are comparing the same variable, obviously they are equal, create another variable and compare.
tempVal = items.fund;
console.log(tempVal);
console.log(tempVal == tempVal); //both are same
You haven't defined the initial value. So obuse a variable compare with them self are always equal. Why are you not using another name for remove complexity also.
var tempVal;
for (i = 0; i < obj.length; i++) {
var items = obj[i];
temp = items.fund;
console.log(temp);
console.log(temp == tempVal);
if(temp == tempVal){
//do something
}
Looking at your code, I thought this is what you're trying to achieve:
var src = [
{
"index": 0,
"fund": 100
},
{
"index": 1,
"fund": 200
},
{
"index": 2,
"fund": 100
}];
var tempFunds = [];
const uniqueFunds = src.filter(item => {
if (tempFunds.indexOf(item.fund) === -1) {
tempFunds.push(item.fund);
return item;
}
});
// logs the array with unique funds
console.log(uniqueFunds);
You can implement an else branch above if you want to deal with duplicate fund(s). Although there is no issue with your choice to use a for loop, you could also consider map or filter function(s) based on your problem.
I am just messing around with generating random human names in JS. I wanted to also practice using the module pattern but I can't get my function to return a normal array.
What I want to save is how often a letter (or set of letters) shows up after another letter.
So with 'jacob' and 'jarod' I should see that the letter 'a' came after the letter 'j' 2 times like this: myArray[j][a] //2
BUT what I have instead somehow turned the array into a set of properties and to figure out that 'a' comes up 2 times I have to check it this way : myArray.j.a //2
can someone explain why this is and how I can fix it?
var names = ['jacob', 'cameron', 'zach', 'lake', 'zander', 'casey', 'carl', 'jeff', 'jack', 'jarod', 'max', 'cat', 'mallory', 'dana', 'hannah', 'stu', 'abrham', 'isaac'];
var probabilities = (function(){
var nextLetterProbability = [];
function addProbability(index, letters){
if(nextLetterProbability[index] !== undefined){
if(nextLetterProbability[index][letters] !== undefined){
nextLetterProbability[index][letters] = nextLetterProbability[index][letters] + 1;
}
else
nextLetterProbability[index][letters] = 1;
}
else{
nextLetterProbability[index] = [];
nextLetterProbability[index][letters] = 1;
}
}
return {
learn:function(names, chainLength){
for (var i = 0; i < names.length; i++) {
var name = names[i];
for (var j = 0; j < name.length - chainLength; j++) {
var start = name[j];
var next = name.slice(j + 1, j + chainLength + 1)
addProbability(start, next);
};
};
},
getLearnedArray:function(){
return nextLetterProbability;
}
}
})();
var nextLetterProbability = []; needed to be var nextLetterProbability = {}; because it is an associative array and is handled as an object.
I have a large array as bellow, now I need to do a group by first column and count the total of that channel existence.
For example:
var original_db = [
["channel1", "online"],
["channel2", "offline"],
["channel3", "online"],
["channel1", "online"],
["lot more"]....
]
Expected result from the original result need to be:
var custom_db = [
["channel1", 2],
["channel2", 0],
["channel3", 1]
]
EDIT:
for(var key in original_db) {
var i;
for (i = 0; i < original_db.length; i += 1) {
if (original_db[i][0] === original_db[key][0]) {
original_db.splice(i, 1);
return;
}
}
}
console.log(original_db);
Use an object whose properties are the first elements to keep the count:
var counts = {};
for (var i = 0; i < original.length; i++) {
var key = original[i][0];
if (counts[key]) {
counts[key]++;
} else {
counts[key] = 1;
}
}
You can then turn this into your final array, although I'm not sure why you prefer that over the counts object:
final = [];
for (var key in counts){
final.push([key, counts[key]]);
}
Convert the array to JSON object and do a loop to get the count.
I don't know if there is a group by, order by in javascript but what you can do create a new array and check if the indexes of channels are set. If it is set, you increment it. If it is not set, and the status is online, you set it to 1, otherwise to 0;
var original_db = [
["channel1", "online"],
["channel2", "offline"],
["channel3", "online"],
["channel1", "online"]
];
var ordered_arr = {};
for(var i=0;i<original_db.length;i++)
{
if(ordered_arr[original_db[i][0]])
ordered_arr[original_db[i][0]]+=1;
else
if(original_db[i][1] =="online")
ordered_arr[original_db[i][0]]=1;
else
ordered_arr[original_db[i][0]]=0;
}
console.log(ordered_arr);
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...
I need to read all the connection times. (connectionTimes)
I need to delete the line - when it will be offline more than online:
userId: 1,
connectionTimes:
[
{onlineTime:"11:10:30", offlineTime:"11:18:12"}, //delete
{onlineTime:"11:14:14", offlineTime:"11:52:41"} //delete
]
Delete user id - When times the connection will be empty.
userId: 1, //delete userid
connectionTimes:
[
//empty connection
]
I have this data structure:
var users = [];
users[0] = {
userId: 1,
connectionTimes:
[
{onlineTime:"11:10:30", offlineTime:"11:18:12"},
{onlineTime:"11:14:14", offlineTime:"11:52:41"}
]
}
users[1] = {
userId: 2,
connectionTimes:
[
{onlineTime:"8:08:14", offlineTime:"1:15:00"}
]
}
You can delete a property from an JavaScript object with the delete operator:
var sampleObject = {
"key1": "value1",
"key2": "value"
};
delete sampleObject["key2"];
or like this:
delete sampleObject.key2
See the Mozilla Developer Network JavaScript Reference for more background on the delete operator:
https://developer.mozilla.org/en/JavaScript/Reference/Operators/delete
Your specific example would look something like this:
for(var id in users) {
var user = users[id];
if (user.connectionTimes.length === 0) {
delete users[id];
break
}
for(var i=0; i<=user.connectionTimes.length; i++) {
var connectionTime = user.connectionTimes[i];
if (connectionTime.onlineTime < connectionTime.offlineTime) {
delete users[id];
break;
}
}
}
Here is a link to jsFiddle showing the code in action:
http://jsfiddle.net/Q86Jd/
There are many ways to remove things from arrays in Javascript. The mains ones I can think of are
The delete operator. Using it sets the chosen position to undefined and is similar to just setting the element to null. (The main difference is that deleting a key will cause it to be skiped when iterating with the forEach and map array methods).
var xs = [0,1,2];
delete xs[1];
console.log(xs); // [0, undefined, 2]
The splice method can remove a chunk or the array, moving the remaining elements left to fill it in.
var xs = [0,1,2,3];
xs.splice(2, 1); //index, ammount to remove
console.log(xs); // [0,1,3]
Setting the array's length property truncates it. This can be used to manually remove elements the old fashioned way when you want more control.
var xs = [0,1,2,3];
xs.length = 2;
console.log(xs); // [0,1]
xs.length = 4;
console.log(xs); // [0,1, undefined, undefined]
So in your case we might do something like this:
function filter_in_place(array, predicate){
var j=0;
for(var i=0; i<arr.length; i++){
var x = arr[i];
if(pred(x)){
arr[j++] = x;
}
}
arr.length = j;
}
for(var i=0; i < users.length; i++){
filter_in_place( users[i].connections, function(conn){
/*return if offline larger then online*/
});
}
filter_in_place(users, function(user){ return user.connections.length > 0; });
Basically you want to use something like this:
for( var i=0; i<users.length; i++) {
for( var j=0; j<users[i].connectionTimes.length; j++) {
if( users[i].connectionTimes[j].onlineTime < users[i].connectionTimes[j].offlineTime) {
delete users[i].connectionTimes[j];
j--;
}
}
if( users[i].connectionTimes.length == 0) {
delete users[i];
i--;
}
}
This is pretty straightforward. In pseudocode:
declare user, times
for each index in users
set user = users[ index ]
set times = user.connectionTimes
if times is empty
then delete users[ index ]
else
declare onlineSecs, offlineSecs
for each index2 in times
set onlineSecs = timeInSeconds( times[ index2 ].onlineTime )
set offlineSecs = timeInSeconds( times[ index2 ].offlineTime )
if offlineSecs > onlineSecs
then delete times[ index2 ]
In JavaScript the command to delete a variable is delete and can be used on arrays the same, e.g. delete someArray[ someIdx ];. The implementation of timeInSeconds will be something like this:
function timeInSeconds( timeWithColons ) {
var hrsMinsSecs = "12:34:56".split(':');
return ( parseInt( hrsMinsSecs[0] ) * 60 +
parseInt( hrsMinsSecs[1] )
) * 60 +
parseInt( hrsMinsSecs[2] )
;
}