Desired:
I have multiple arrays of players, roundWinners, being iterated through in a FOR loop. For each array, I need the MODE of the array (the most frequently occurring value) assigned to a new variable winner.
I am lost as to where to start, so I ask what is the most efficient way to go about accomplishing this?
Example:
for (i = 0; i < numberOf; i++) {
var roundWinners[0] = ["Joe", "Joe", "Bob", "Sue"]
var winner[0] ="Joe";
var roundWinners[1] = ["Joe", "Sue", "Bob", "Sue"]
var winner[1] ="Sue";
var roundWinners[2] = ["Bob", "Bob", "Bob", "Sue"]
var winner[2] ="Bob";
}
Prior to the loop, create an object.
var ArrMode = {};
Then, on each iteration, take the name, and, using it as a property name, see if the object has a property of that name. If so, increment the value of that property.
If not, add that property, setting its value to 1.
After processing the array, then process the object, using a simple replace-if-greater test. Each time you make a replacement, hold the name of that property as the winner.
Once you have processed the whole object, the property name you are holding is the name of the winner.
I don't actually have an answer
One person posted this as a way to iterate through the properties of a JS object, when you do not know the property names at design time:
for (var property in object) {
if (object.hasOwnProperty(property)) {
// do stuff
}
}
You can add a property to a JS object at any time, using:
obj[theName] = theVal; // the name’d be a string, theVal’d be anything
// Like:
var theName = "John";
obj[theName] = 1;
So, you would create an empty object before the loop with a name (like, say "modes"), but no properties
var modes = {};
Then, in each iteration over the array, iterate through the object's properties, checking the name of the properties against the current name in the array.
If found, then use:
modes[arr[i]]++;
If not found, then use
modes[arr[i]] = 1;
After the iterating over the array, iterate over the object's properties, checking their values, and 'remembering' the name and value of the highest one.
Working:
//Mode Calc
function mode( arr ) {
if ( !Array.isArray( arr ) ) {
throw new TypeError( 'mode()::invalid input argument. Must provide an array.' );
}
var len = arr.length,
count = {},
max = 0,
vals = [],
val;
for ( var i = 0; i < len; i++ ) {
val = arr[ i ];
if ( !count[ val ] ) {
count[ val ] = 0;
}
count[ val ] += 1;
if ( count[ val ] === max ) {
vals.push( val );
} else {
max = count[ val ];
vals = [ val ];
}
}
return vals.sort( function sort( a, b ) {
return a - b;
});
} // end FUNCTION mode()
for (i = 0; i < numberOf; i++) {
winner = ( mode( roundWinners[i] ) );
}
Related
I have a dynamically-generated object like so (I'm just noting the 'children' array keys here for display purposes, assume its an otherwise syntactically sound array):
foo: {
children: [
0: {
children: [
3: {
children: [
6: {
//...etc
I then have a list of keys being generated:
var keys = [0,3,6];
And I need to set the value of the element of the array described by the list of keys, as such:
foo.children[0].children[3].children[6] = "bar";
Any ideas? I've tried a few different recursive techniques, but I'm missing something somewhere.
While you could do this recursively, I think it is more efficient to do it in a loop like this:
function setNestedChild( obj, path, value ){
var child = obj;
path.forEach(function( i, idx ){
if( idx == path.length - 1 ){
child.children[ i ] = value;
}
else {
child = child.children[ i ];
}
});
}
How about a method along the lines of
def function getElement (keys) {
var el = this.foo
for (i = 0; i < keys.length; i++) {
el = el.children[keys[i]]
}
return el
}
This function is just to retrieve the desired element doesn't actually set the value.
How about this?
function setVal(obj, keys, val){
var temp = obj;
while(keys.length){
var i = keys.pop();
if(!keys.length) return temp.children[i] = val;
temp = temp.children[i];
}
}
I have an object that is being returned from a database like this: [{id:1},{id:2},{id:3}]. I have another array which specified the order the first array should be sorted in, like this: [2,3,1].
I'm looking for a method or algorithm that can take in these two arrays and return [{id:2},{id:3},{id:1}]. Ideally it should be sort of efficient and not n squared.
If you want linear time, first build a hashtable from the first array and then pick items in order by looping the second one:
data = [{id:5},{id:2},{id:9}]
order = [9,5,2]
hash = {}
data.forEach(function(x) { hash[x.id] = x })
sorted = order.map(function(x) { return hash[x] })
document.write(JSON.stringify(sorted))
function sortArrayByOrderArray(arr, orderArray) {
return arr.sort(function(e1, e2) {
return orderArray.indexOf(e1.id) - orderArray.indexOf(e2.id);
});
}
console.log(sortArrayByOrderArray([{id:1},{id:2},{id:3}], [2,3,1]));
In your example, the objects are initially sorted by id, which makes the task pretty easy. But if this is not true in general, you can still sort the objects in linear time according to your array of id values.
The idea is to first make an index that maps each id value to its position, and then to insert each object in the desired position by looking up its id value in the index. This requires iterating over two arrays of length n, resulting in an overall runtime of O(n), or linear time. There is no asymptotically faster runtime because it takes linear time just to read the input array.
function objectsSortedBy(objects, keyName, sortedKeys) {
var n = objects.length,
index = new Array(n);
for (var i = 0; i < n; ++i) { // Get the position of each sorted key.
index[sortedKeys[i]] = i;
}
var sorted = new Array(n);
for (var i = 0; i < n; ++i) { // Look up each object key in the index.
sorted[index[objects[i][keyName]]] = objects[i];
}
return sorted;
}
var objects = [{id: 'Tweety', animal: 'bird'},
{id: 'Mickey', animal: 'mouse'},
{id: 'Sylvester', animal: 'cat'}],
sortedIds = ['Tweety', 'Mickey', 'Sylvester'];
var sortedObjects = objectsSortedBy(objects, 'id', sortedIds);
// Check the result.
for (var i = 0; i < sortedObjects.length; ++i) {
document.write('id: '+sortedObjects[i].id+', animal: '+sortedObjects[i].animal+'<br />');
}
To my understanding, sorting is not necessary; at least in your example, the desired resulting array can be generated in linear time as follows.
var Result;
for ( var i = 0; i < Input.length; i++ )
{
Result[i] = Input[Order[i]-1];
}
Here Result is the desired output, Input is your first array and Order the array containing the desired positions.
var objArray = [{id:1},{id:2},{id:3}];
var sortOrder = [2,3,1];
var newObjArray = [];
for (i in sortOrder) {
newObjArray.push(objArray[(sortOrder[i]) - 1])
};
Why not just create new array and push the value from second array in?? Correct me if i wrong
array1 = [];
array2 = [2,3,1];
for ( var i = 0; i < array2 .length; i++ )
{
array1.push({
id : array2[i]
})
}
When I try to convert the array below to a string using JSON.stringify, I get to see empty square brackets only. I tried console.log to debug, but I do see the data I want to convert into a string, so what am I doing wrong here? Any help will be much appreciated!
function jsonSuccess( data ){
var jsonArr = new Array();
for( var i = 0; i < data.length; i++ ){
var shipInfo = new Array();
var shipRows = new Array();
$.each( data[i], function( key, value ){
if ( key == "EniNumber" ) {
shipInfo['E'] = value;
//console.log( shipInfo.E );
}
if ( key == "Name" ) {
shipInfo['N'] = value;
}
if ( key == "StartDate" ) {
shipInfo['S'] = value;
}
if ( key == "Rows" ) {
$.each( value, function( subKey, subValue ){
var rowContent = {
"T": subValue.T,
"X": subValue.X,
"Y": subValue.Y,
"D": subValue.D
}
shipRows.push( rowContent );
});
shipInfo['R'] = shipRows;
}
});
jsonArr[i] = shipInfo;
var myJsonString = JSON.stringify(jsonArr);
console.log(myJsonString);
}
}
You are using an Array as an object.
In Javascript you have Arrays and objects. But as you may know Arrays are also objects and this has some weird implications.
var arr = [];
arr[0] = "foo"; // this is fine
console.log(JSON.stringify(arr)); // [ "foo" ]
arr.length; // 1 ok
But since an Array is an object, we can also assign properties:
arr.foo = "bar";
console.log(arr); // [ 0: "foo", foo: "bar" ]
console.log(JSON.stringify(arr)); // [ "foo" ] .. where did bar go?
arr.length; // 1 huh?
We're mixing array values and object properties.
The JSON encoder looks at the object and sees that it's an (instanceof) Array and serializes it. It looks at arr.length (which is 1 in the example) so you get just [ "foo" ]. The properties on the array are ignored.
It's important to realize the difference between array valus and object properties. Arrays in JavaScript are never associative. If you set a property on an Array it wont increase the length and it wont show up if you loop over it in a for-loop.
Change:
var shipInfo = new Array();
To:
var shipInfo = {};
shipInfo is not an array, it is an object so try var shipInfo = {};
Demo: Problem, Solution
I'm trying to create a new object for each item in an array by looping. The names of the objects should be based on the key of the array.
So for this array:
var arr = new Array(
"some value",
"some other value",
"a third value"
);
Would result in three objects:
alert(object1.value);
alert(object2.value);
alert(object3.value);
The code I have thus far (but isn't working) is:
// Object
function fooBar(value) {
this.value = value;
...
}
// Loop
var len = arr.length;
for (var i = 0; i < len; i++) {
var objectName = object + i;
var objectName = new fooBar(arr[i]);
}
Does what I'm asking for even make sense?
You have to make an array of the objects also
var objs = new Array();
for(var i = 0; i < len; i++) {
objs[i] = new fooBar(arr[i]);
}
alert(objs[0].value);
You can map your array:
var arr = new Array(
"some value",
"some other value",
"a third value"
);
var fooBars = arr.map(function(x) { return new fooBar(x); });
Then you can access each value:
alert(fooBars[0].value);
// etc.
or process them all at once:
fooBars.forEach(function (foo) { alert(foo.value); });
What you're asking for makes sense, but shouldn't be how you're building you JavaScript out.
Technically, there is a way of creating vars with names you build dynamically, but you shouldn't use it as it's slow, and if users are specifying what's in the array, it's unsafe and the feature is being needed in a couple of years, so your old stuff might break in future browsers.
Meanwhile, you could easily do something like:
var obj = {},
arr = [ "one", "two", "three" ],
i = 0,
len = arr.length,
val = "",
name = "";
for (; i < len; i += 1) {
name = "item" + i;
val = arr[i];
obj[name] = val;
}
Now you can call obj.item1; // "two"
If you're really desperate, you can use window as obj so when you're writing stuff in the global scope, you can just write item0; // "one" but this really isn't a great idea, for several reasons (readability, maintainability, likelihood of overwriting somebody else's properties, etc).
If you really want the variable named so, here's a solution
function fooBar(value) {
this.value = value;
}
var arr = new Array(
"some value",
"some other value",
"a third value"
);
(function(context) {
for ( var i = 0; i < arr.length; i++) {
var key = 'object' + ( i + 1 );
this[ key ] = new fooBar( arr[ i ] );
}
}(window));
alert(object1.value);
alert(object2.value);
alert(object3.value);
If you don't want global variables object1 ... just replace the keyword window with this and it will produce local variable to the current scope.
Test it out here: http://jsfiddle.net/bukart/F8ham/1/
I have an array of states:
['CO','CA','CO','AL', ... ,'NV']
and I'd like to reduce to:
{ 'CO': 9, 'CA':17, 'AL':1, etc}
The value is the number of times each state occurs in the array.
what's the most efficient way to do this?
function compress2dict( raw_arr )
{
var ret={};
for(var i=0;i<raw_arr.length;i++)
{
var item=raw_arr[i];
ret[item]|=0;
ret[item]++;
}
return ret;
}
a = ['CO','BO','CO','CC','CC','CO','CC']
b = compress2dict(a)
b
{'BO':1, 'CC':3, 'CO':3}
You may be interested in array_count_values from PHPJS. Since the PHP array_count_values function does exactly what you want, it stands to reason that the JavaScript port of that function fits.
I expect you just iterate over the array, assign the member values to object property names and the number of occurences as the value:
function toObj(arr) {
var item, obj = {};
for (var i=0, iLen=arr.length; i<iLen; i++) {
item = arr[i];
obj[item]? ++obj[item] : (obj[item] = 1);
}
return obj;
}
Or if you like while loops (sometimes they're faster, sometimes not):
function toObj(arr) {
var item, obj = {}, i = arr.length;
while (i) {
item = arr[--i];
obj[item]? ++obj[item] : (obj[item] = 1);
}
return obj;
}