Related
Im trying to split all the numbers in a array:
var array_code = [116,101,120,116];
So i want the result to look like this: [1,1,6,1,0,1,1,2,0,1,1,6]
the code im working on right now looks like this:
var array_gesplit = new Array;
for(var i=0; i< array_code.length; i++){
console.log(array_code[i])
while (array_code[i]) {
array_gesplit.push(array_code[i] % 10 );
array_code[i] = Math.floor(array_code[i]/10);
}
}
The result im getting from this is:
[
6, 1, 1, 1,
0, 1, 0, 2,
1, 6, 1, 1
]
Who can help me ?
You can use Array.from() method for this:
var array_code = [116,101,120,116];
var result = Array.from(array_code.join(''), Number)
console.log(result)
Explanation:
array_code.join('') creates a string like "116101120116"
Array.from('116101120116') on this string results in new Array of strings like:
["1", "1", "6", "1", "0", "1", "1", "2", "0", "1", "1", "6"]
We can also use Array.from() with map function, so that we can convert all these string values to Number in one line like:
Array.from(array_code.join(''), x => Number(x))
Or, just Array.from(array_code.join(''), Number)
The above logic result is the required output.
You can use flatMap() and convert number to string and use built-in split() method.
var array_code = [116,101,120,116];
const res = array_code.flatMap(x => x.toString().split('').map(Number));
console.log(res)
You could take strings and map numbers.
var code = [116, 101, 120, 116],
result = code.flatMap(v => Array.from(v.toString(), Number));
console.log(result);
Here's a hack by using some details of the JavaScript language:
var array_code = [116, 101, 120, 116];
var array_string = JSON.stringify(array_code);
var array_parts = [].slice.call(array_string);
var parts = array_parts.slice(1, -1); // get rid of the square brackets
console.log(parts);
I have been trying to receive an object as a parameter and return it as an array but no luck. I don't see why it could be any problems in the code. I might be lost at this point or just completely out of the logic.
function att(testobj) {
var q = "";
for(var i = 0; i < testobj.length ; i++){
q += testobj[i] + " ";
}
return q;
}
var obj1= {
Big: 10,
low: 5
};
var attObj1= att(obj1);
console.log(attObj1);
var obj2= {
a: 10,
b: 20,
c: 30
};
var attObj2= att(obj2);
console.log(attObj2);
I did try as in the code do a for-loop where it check each array length and sort it by using q += testobj[i] but I'm not getting any results. Just a blank console log.
This article may help you object.keys()
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.keys(obj)); // console: ['0', '1', '2']
var obj = { key0: 'value-0', key1: 'value-1', key2: 'value-2' };
console.log(Object.keys(obj)); // console: ['key0', 'key1', 'key2']
You could iterate over the keys and return the joind value.
Method used:
Object.keys for getting all keys from the object,
Array#join convert an array to a string with the given string as glue.
function att(testobj) {
return Object.keys(testobj).join(', ');
}
var obj1= {
Big: 10,
low: 5
};
var attObj1= att(obj1);
console.log(attObj1);
var obj2= {
a: 10,
b: 20,
c: 30
};
var attObj2= att(obj2);
console.log(attObj2);
Although an Array is technically an Object, one difference is that they can be iterated over.
So for example you can do:
var someArray = ['some', 'value', 'here'];
for (var i = 0; i <= someArray.length; i++) {
console.log(someArray[i]);
}
However, with an object you cannot as it doesn't contain the iterate functionality.
If you want to iterate through an Object and an Array interchangeably, you need to consider using a method that supports both.
For example:
function iterateOver(obj) {
for (var k in obj) {
console.log('Key', k, 'Value', obj[k]);
}
}
var someArray = ['some', 'value', 'here'];
var someObject = {
some: 'value',
another: 'great_value'
};
iterateOver(someArray);
iterateOver(someObject);
I have an array with infos about a group of people : name, current status, new points, last event points
Example:
var group = new Array();
group[0] = "John Doe,beginer,14,7";
group[1] = "Lois Lane,advanced,13,9";
group[2] = "Bruce Waine,advanced,17,10";
I need a function that calculates the average of the new points.
For the previous example the average would be (14+13+17)/3 = 14.66666666666667
It'd be a heck of a lot easier if you convert the data in the array from strings to objects This will benefit you in two ways: 1) the code will be more readable, understandable, and easier to maintain, and 2) you won't have to do a bunch of string gymnastics to pull out the relevant data.
Do something like this:
var group = [
{ name: 'John Doe', status: 'beginner', newPoints: 14, eventPoints: 7 },
{ name: 'Lois Lane', status: 'advanced', newPoints: 13, eventPoints: 9 },
{ name: 'Bruce Waine', status: 'advanced', newPoints: 17, eventPoints: 10 }
];
function getAverageNewPoints(people) {
var count = people.length || 0,
average = 0;
for (var i = 0; i < count; i++) {
average += people[i].newPoints;
}
return average / count;
}
alert('The average of new points in the group is: ' + getAverageNewPoints(group));
Try the following:
function groupAverage(group) {
var sum = 0;
var count = group.length;
for (var i in group) {
sum += parseInt(group[i].split(',')[2], 10);
}
return sum / count;
}
Split the String at , and get the values and convert them to Number.
var group = new Array();
group[0] = "John Doe,beginer,14,7";
group[1] = "Lois Lane,advanced,13,9";
group[2] = "Bruce Waine,advanced,17,10";
sum=0;
for(var i in group)
{
sum=sum+Number(group[i].split(",")[2]);
}
console.log(sum/group.length);
You have a bad data structure for this. You don't want to use strings. You also should not use the Array constructor. Start with:
var group = [
{name: "John Doe", rank: "beginner", points: 14, lastScore: 7},
{name: "Lois Lane", rank: "advanced", points: 13, lastScore: 9},
{name: "Bruce Wayne", rank: "advanced", points: 17, lastScore: 10},
],
length = group.length,
sum = 0,
i;
for ( i = 0; i < length; ++i) {
sum += group[i].points;
}
return sum / length; // Or do something else with the result.
// I did no error checking.
You could use an object constructor instead of the inline Object I used, but that's not really necessary. I'm just curious; did you use strings as a default, or was using a string interface part of a textbook assignment?
Oh, one reason to use [] instead of new Array() is that when you construct an Array, the value is always truthy, while [] is falsy.
I did take the liberty of correcting Bruce's last name.
I have an array of objects that is currently like this, in which entries are ordered by date and time:
var checkin_data = [
{id: 430, date: "2013-05-05", time: "08:24"},
{id: 435, date: "2013-05-06", time: "04:22"},
{id: 436, date: "2013-05-06", time: "05:36"},
{id: 437, date: "2013-05-06", time: "07:51"},
{id: 488, date: "2013-05-06", time: "08:08"},
{id: 489, date: "2013-05-06", time: "10:12"},
{id: 492, date: "2013-05-06", time: "13:18"},
{id: 493, date: "2013-05-06", time: "15:55"},
{id: 494, date: "2013-05-06", time: "18:55"},
{id: 498, date: "2013-05-06", time: "22:15"},
{id: 501, date: "2013-05-07", time: "11:40"},
{id: 508, date: "2013-05-07", time: "18:00"},
{id: 520, date: "2013-05-08", time: "04:48"},
{id: 532, date: "2013-05-09", time: "21:11"},
{id: 492, date: "2013-05-10", time: "11:45"},
{id: 601, date: "2013-05-11", time: "18:12"}
];
The dates represent a date in a particular week: I'd like to sort this array in order to lay it out in "rows", so the data needs to be re-sorted to lay out like this (note the order of the dates):
var checkin_data = [
{id: 430, date: "2013-05-05", time: "08:24"},
{id: 435, date: "2013-05-06", time: "04:22"},
{id: 501, date: "2013-05-07", time: "11:40"},
{id: 520, date: "2013-05-08", time: "04:48"},
{id: 532, date: "2013-05-09", time: "21:11"},
{id: 492, date: "2013-05-10", time: "11:45"},
{id: 601, date: "2013-05-11", time: "18:12"},
{id: 436, date: "2013-05-06", time: "05:36"},
{id: 508, date: "2013-05-07", time: "18:00"},
{id: 437, date: "2013-05-06", time: "07:51"},
{id: 488, date: "2013-05-06", time: "08:08"},
{id: 489, date: "2013-05-06", time: "10:12"},
{id: 492, date: "2013-05-06", time: "13:18"},
{id: 493, date: "2013-05-06", time: "15:55"},
{id: 494, date: "2013-05-06", time: "18:55"},
{id: 498, date: "2013-05-06", time: "22:15"}
];
Getting the data in that order would allow me to lay out a table like this:
Thanks, any help would be appreciated.
Here is a suggestion using functional methods:
Reduce the list into arrays of buckets based on day, and sort that list (this is like reading the table you've got on rows)
Iterate through the rows in order, clear out unused ones.
Here:
//first, we collapse the array into an array of buckets by day
half_sorted = checkin_data.reduce(function(accum,cur){
var bucket = new Date(cur.date).getDay();
accum[bucket].push(cur);
return accum;
},[[],[],[],[],[],[],[]]).map(function(day){
return day.sort(function(x,y){ // now we sort each bucket
return new Date("01-01-1990 "+x.time) - new Date("01-01-1990 "+y.time);
});
});
// At this point, we have an array with 7 cells looking like your table
// if we look at its columns.
// finally, we push to the result table.
var result = [];
var daysToClear = 7;
for(var i=0;daysToClear>0;i=(i+1)%7){
if(half_sorted[i] && half_sorted[i].length > 0){
result.push(half_sorted[i].pop());
}else if(half_sorted[i] && half_sorted[i].length === 0){
half_sorted[i] = null;
daysToClear--;
}
}
Working fiddle
First of all, I think you're going about this in the wrong way. Please see my note below the following code.
To do exactly as you've asked, here's one way:
// parsing the date strings ourselves avoids time zone problems
function dateFromString(string) {
var parts = string.split('-');
return new Date(parseInt(parts[0], 10),
parseInt(parts[1], 10) - 1,
parseInt(parts[2], 10));
}
The above is a utility function.
var i, l, dates = [[], [], [], [], [], [], []], item;
// place the objects into dow-sorted buckets
for (i = 0, l = checkin_data.length; i < l; i += 1) {
item = checkin_data[i];
dates[dateFromString(item.date).getDay()].push(item);
}
i = 0;
l = 0;
checkin_data = [];
while (true) { // instead of a for loop to handle the row-wrap manually
if (dates[i][l]) {
item = dates[i][l];
checkin_data.push(item);
}
i += 1;
if (i === 7) {
if (!item) {
break; // we had a complete row with no data
}
item = undefined;
l += 1;
i = 0;
}
}
checkin_data is now sorted in the order you requested.
Note: you really don't need the second loop, because it is doing most of the work you'll have to do again to use the provided array. So in your routine for writing out the table, instead just use the data structure that the first loop creates. You would of course need a slightly different bailout strategy since you don't want to create an extra blank row, but I'll leave that up to you.
After a bit of thought, though, I came up with another way to do it, if you don't mind adding a new key to your objects:
function dateFromString(string) {
var parts = string.split('-');
return new Date(parseInt(parts[0], 10),
parseInt(parts[1], 10) - 1,
parseInt(parts[2], 10));
}
var i, l, counts = [0, 0, 0, 0, 0, 0, 0], item, dow;
for (i = 0, l = checkin_data.length; i < l; i += 1) {
item = checkin_data[i];
dow = dateFromString(item.date).getDay();
item.sortKey = ++counts[dow] * 7 + dow;
}
checkin_data.sort(function(a, b) {
return a.sortKey - b.sortKey;
});
I've come up with a solution, maybe not the most elegant, but it's working:
var sorted_data = [], elements_to_dump = [], i, j, tmp;
while (checkin_data.length > 0) {
for (i = 0; i < checkin_data.length; i++) {
if (checkin_data[i-1]) {
if (checkin_data[i-1].date === checkin_data[i].date) {
continue;
}
}
sorted_data.push(checkin_data[i]);
elements_to_dump.push(checkin_data[i].id);
}
for (j = 0; j < elements_to_dump.length; j++) {
for (i = 0; i < checkin_data.length; i++) {
if (checkin_data[i].id === elements_to_dump[j]) {
tmp = checkin_data.splice(i, 1);
break;
}
}
}
}
I'd like to sort this array in order to lay it out in "rows", so the data needs to be re-sorted [into this linear representation]. Getting the data in that order would allow me to lay out a table
No, it does not need to be. Actually, that's one step too much, and the order of your intermediate result makes absolutely no sense. What you should do instead is construct a (weekday-) list of (entries-per-day-) lists:
var days = [];
for (var i=0, date=null, day; i<checkin_data.length; i++) {
var entry = checkin_data[i];
if (entry.date !== date)
days.push(day = []);
day.push(entry);
}
That's it, you have you two-dimensional format now. Well, maybe you will need to transpose it to get it into the table you wanted, but that's not too complicated either:
var header = [],
table = [header]; // or create a DOM or a HTML string or whatever
for (var i=0; i<days.length; i++)
header.push(days[i][0].date /* or the weekday name? */);
for (var r=0; !done; r++) {
var row = [],
done = true;
// create cells:
for (var i=0; i<days.length; i++)
if (days[i].length > r) {
row[i] = days[i][r].time;
done = false;
} else
row[i] = "";
}
if (!done)
table.push(row);
}
What you're trying to do is very simple. This is what I would do:
var groups = groupBy(checkin_data, "date"); // groups items based on date
var table = zipAll.apply(null, toArray(groups)); // zips corresponding elements
// of each group into an array
After this you may create your table as follows:
var header = getHeader(groups), rows = map(table, getRow);
document.body.appendChild(getTable(header, rows));
Of course the actual code would be much bigger (a little more than 100 lines of code) since you need to write the logic for groupBy, toArray, zipAll, map, getHeader, getRow, getTable, etc.
Luckily for you I had the time to go and write all this stuff. Hence you now have a working demo: http://jsfiddle.net/hZFJw/
I would suggest that you browse through my code and try to understand how it works. It's too much to explain in one answer.
Note: My solution may be more than 100 lines of code. However it's still a simple solution because:
The actual code which generates the table is just 4 lines long and is very simple to understand.
The rest of the code is composed of reusable functions like groupBy, zipAll and map. These functions are very small and simple to understand.
Overall by abstracting the program into reusable functions the size of the program has increased. However the complexity of the program has considerably decreased.
You could achieve the same result by tackling the problem in an imperative style like most other answers do. However doing so makes the program harder to understand. Compare my code with other answers and see for yourself.
You can sort array with Alasql JavaScript library.
alasql.fn.WEEKDAY = function(d) { // User-defined function
return (new Date(d)).getDay();
};
var res = alasql('SELECT *, WEEKDAY(date) AS dow FROM ? ORDER BY dow', [checkin_data]);
Try this example at jsFiddle.
How would one sort the following object to correct alphabetical order of names?
var users_by_id = {
'12': ['Ted', 34, 'Male'],
'13': ['Ben', 36, 'Male'],
'14': ['Alice', 42, 'Female']
}
var users_by_name = {
'14': ['Alice', 42, 'Female'],
'13': ['Ben', 36, 'Male'],
'12': ['Ted', 34, 'Male']
}
I have a plan which would need two passes over the object, but I am not sure if there is a simpler way to do it. The plan I have is this (I am using jQuery):
var users_by_name = {};
var names = [];
$.each(users_by_id, function(id, props) {
names.push(props[0]);
});
names.sort();
$.each(names, function(i, n) {
$.each(users_by_id, function(id, props) {
if(n == props[0]) users_by_name[id] = props;
});
});
If you want to keep your Object based storage instead of using an Array, you'll need to create Arrays of the properties of the Object, and sort that to get an order.
var users = {
'12': ['Ted', 34, 'Male'],
'13': ['Ben', 36, 'Male'],
'14': ['Alice', 42, 'Female']
};
var props = Object.keys(users);
var user_props_by_name = props.slice().sort(function(prop_a, prop_b) {
return users[prop_a][0].localeCompare(users[prop_b][0]);
});
var user_props_by_age = props.slice().sort(function(prop_a, prop_b) {
return users[prop_a][1] - users[prop_b][1];
});
Then you can iterate the Array and use the property names to look up items in the Object.
user_props_by_name.forEach(function(prop) {
console.log(users[prop]);
});
user_props_by_age.forEach(function(prop) {
console.log(users[prop]);
});
This will take some maintenance though when adding and removing users. You would probably want to create a layer that adds and removes users, and updates the sort Arrays at the same time.
sort takes an optional parameter which is a compare function
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/sort
var data =[
['Ted', 34, 'Male'],
['Ben', 36, 'Male'],
['Alice', 42, 'Female']
];
var sortbyid = data.sort(function(a,b){return a[1]<b[1] ? -1 : a[1]>b[1] ? 1 : 0});
var sortbyname = data.sort(function(a,b){return a[0]<b[0] ? -1 : a[0]>b[0] ? 1 : 0});
Sorting is usually made when you have to iterate on a collection. So... my suggestion is to ad to methods to your object's prototype - .keysById and .keysByName which have to return keys ordered by the condition you mentioned above. So when you have to iterate by name you can do:
var kbn = yourObj.keysByName();
for(var i=0; i<yourObj.length;i++) {
... yourObj[kbn[i]] ....
}
You can do this methods, i'm sure, so I won't give examples.
yourObj.prototype.keysByName = function() { ... }
OK, I got it. As has been pointed in the comments, Objects do not have any order. So no matter in what order the members are added (or defined), iterating over the object will produce the same result.
So, I should change my approach. A bit of background is neccessary to see why the new method would work (which is missing in the question by the way).
I have a users table and I want to display an html table with users in alphabetical order like so:
<tr id="user-N"><td>NAME</td><td>AGE</td><td>GENDER</td></tr>
And here is what I came by:
var name_ids = [];
var trows = '', thisNID;
$.each(users_by_id, function(id, props) {
name_ids.push(props[0]+':'+id);
});
name_ids.sort();
$.each(name_ids, function(i,nid) {
thisNID = nid.split(':');
trows += '<tr id="user-' + thisNID[1] + '">';
trows += '<td>' + users_by_id[thisNID[1]][0] + '</td>';
trows += '<td>' + users_by_id[thisNID[1]][1] + '</td>';
trows += '<td>' + users_by_id[thisNID[1]][2] + '</td>';
trows += '</tr>';
});
Another option that makes use of Array.prototype.sort function
var users_by_id = {
'0': ['Ted', 34, 'Male'],
'1': ['Ben', 36, 'Male'],
'2': ['Alice', 42, 'Female']
}
// as long as length is bigger than max object key value
users_by_id.length = Object.keys( users_by_id ).length;
Array.prototype.sort.call( users_by_id, function( a, b ) {
var aName = a[0].toLowerCase();
var bName = b[0].toLowerCase();
if( aName > bName ) return 1;
if( aName < bName ) return -1;
return 0;
});
There are a few caveats to the above:
The object must contain a length property
The length property must have a value larger than the max value of the object keys
If you do not use contiguous numbers as keys and do the following:
var users_by_id = {
'12': ['Ted', 34, 'Male'],
'13': ['Ben', 36, 'Male'],
'14': ['Alice', 42, 'Female']
}
Once sorted the object's sorted numeric keys will be renamed => 0,1,2
Take a look at the fiddle here