I have the following javascript array:
a=[0, "b", 2, 3, 4, 5, 1, 9, 8, "A", "a", 11010]
Now I want to sort it and I do it like this
a.sort()
But then I get the following:
[0, 1, 11010, 2, 3, 4, 5, 8, 9, "A", "a", "b"]
Which I think is wrong because 11010 is greater than 2 and it should be after 2.
Also even if I do the following:
a.sort(function(a,b){return a-b;});
I get the following:
[0, "b", 11010, 2, 3, 4, 1, 8, 9, "A", "a", 5]
Can someone explain me why this is happening?Thank you
The problem is that, when sorting, JavaScript treats all the array elements as strings by default.
JavaScript is not type-safe, like Haskell or Java. This means that you can perform all sorts of crazy actions like adding numbers and strings, or comparing strings to numbers without throwing an error.
UTF-8 Character Code Table
As you can see in this table, 1 gets a value of 49, which is less than the value of 97 for a lower case a
"1" gets placed before "10110" for the same reason that "a" gets sorted before "apple"
This video covers a lot of the highly unexpected default patterns of JavaScript that result from dissimilar type operations.
Take a look at how array.sort works at this link.
If you don't provide your own sorting function, then
"elements are sorted by converting them to strings and comparing
strings in Unicode code point order."
As a string, 11010 comes before 2. You haven't provided a sort function, so the sort method is using the default behavior.
This is why you're seeing the behavior you've noted.
Your array has both numbers and strings. What you need to do is supply a compare function.
a = [0, "b", 2, 3, 4, 5, 1, 9, 8, "A", "a", 11010]
a.sort(function(c1, c2) {
if(typeof c1 === "number" && typeof c2 == "number") {
return c1 - c2;
} else {
return (c1 + "").localeCompare(c2);
}
);
Related
So my brain is on shut down.
I have a c3 graph that accepts arrays of numbers so it can display the bars on the graph. I'm having trouble parsing the data that is coming from our backend into these arrays dynamically.
I have three variables
var inp = graphNums.inProgress;
var rec = graphNums.received;
var att = graphNums.attention;
That produces data in a key value pair that looks like this
{group1: 3, group2: 0, group3: 0}
These groups match with the x access along the bottom of the graph doing something like this.
for (i in inp) {
if (inp.hasOwnProperty(i)) {
cat.push(i)
}
}
cat.unshift('x'); //x needs to be there for the graph to work
Here is where the issue lies. The graph only accepts the values like this.
['Rec', 5, 1, 4, 8, 5, 3],
['InP', 7, 2, 7, 9, 7, 3],
['Res', 10, 5, 2, 9, 5, 2],
For the life of me I cannot figure out how to get the key value pair to match up with this array. Any help would be appreciated.
A jsfiddle with the full graph and example.
http://jsfiddle.net/17sqrnec/5/
I suggest to have a look at the documentation here : http://c3js.org/samples/data_json.html
You will find the JSON Format that can be used for categories, which would be for instance:
{category: 'cat1', group1: 3, group2: 0, group3: 0}
you need to provide an array with the x categories/labels
and remaining arrays will be considered data with a leading label, matching those of defined x categories
a working fiddle: http://jsfiddle.net/17sqrnec/45/
have anybody any suggestion to "deal" a array after filling it randomly with recurring integers?
here is a easy example (3 x integer-group: 1,2,3,4):
array[1,2,3,4,4,2,3,1,1,4,3,2];
is there a way with a special function, to "rearrange" the array, by avoiding the same integers side by side.
this would be OK (no immediate neighbor is identical):
array[1,2,1,2,1,3,4,3,4,3,4,2];
those are not:
array[4,4,4,1,2,3,3,2,1,1,2,3];
array[1,2,3,2,1,3,3,4,4,1,2,4];
in my case the array could have 25 to 30 times the same integer-group.
hopefully I'm declaring comprehensible - so, you understanding my problem!
Thank you in advance for your efforts
FerO
Edited for clarity:
All integers must be conserved (not deleted) and the integers could be between 0 and 99!
changed "clean" to "rearrange"
Okay, now that I understand what you're after better - here you are. First, a caveat: there are arrays for which this is impossible. For instance, any array in which more than half the elements have the same value cannot be shuffled to keep those values away from each other.
That said:
var insert = function(val,arr) {
if (arr.length > 1) {
for (var i=1;i<arr.length;i++) {
if (arr[i-1] !=val && arr[i] != val) {
arr.splice(i,0,val);
return arr;
}
}
}
arr.splice(0,0,val);
return arr;
}
var shuffle = function(arr) {
return arr.reduce(function(p,c,i,a) {
return insert(c,p);
}, []);
}
shuffle() returns a new array built by shuffling the values of the input array; if you'd rather have them shuffled 'in place' by mutating the input array, that's easy enough to do. There may exist theoretically-shuffleable arrays which this algorithm fails for. I haven't found any in brief testing, but I also haven't proven they don't exist.
The algorithm here is:
Start with an empty 'destination' array.
For each element in the input array, traverse the destination array and insert it into the first position found where it does not equal either of its neighbors.
If no such position is found, stick it at the front.
(This would perform slightly better if it weren't ignoring the possibility of putting things in position 0 right off)
shuffle([4,4,4,3,3,3,2,2,2,1,1,1,1]) = [3, 1, 2, 1, 4, 1, 2, 1, 3, 2, 4, 3, 4]
shuffle([1,2,3,4,4,2,3,1,1,4,3,2,2]) = [2, 3, 2, 4, 2, 1, 3, 1, 4, 2, 3, 4, 1]
shuffle([1,1,1,1,1,1,1,2,2,2,2,2,2,2]) = [2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1]
JSfiddle
You can use Array.prototype.filter() to remove values that are adjacent to identical values.
var myArray = [1, 2, 3, 4, 4, 2, 3, 1, 1, 4, 3, 2];
var deduped = myArray.filter(function (value, index, collection) {
return value !== collection[index+1];
});
// deduped is now [1, 2, 3, 4, 2, 3, 1, 4, 3, 2]
I found many posts on stack overflow about that similar subject but none of them solve this issue here.
<script>
//Array GanginaA contains duplicated values.
//Array GanginaB contains only unique values that have been fetched from GanginaA
GanginaA=[0,1,2,3,4,5,5,6,7,8,9,9];
GanginaB=[0,1,2,3,4,5,6,7,8,9];
var hezi=<!--The Magic Goes Here-->
console.log(hezi);
/*
* Expected Output:
* 5,9
*/
</script>
GanginaA will always be longer or identical to GanginaB so there is no reason to calculate by the value of the longer array length.
GanginaB will always contains unique values that taken from GanginaA so it will always be the shorter array length or identical to GanginaA array.
Now it makes it a lot easier to find doubles.
You can use filter to get the elements like below
GanginaA = [0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 9];
GanginaB = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var hezi = GanginaB.filter(function (item, index) {
return GanginaA.indexOf(item) !== GanginaA.lastIndexOf(item)
});
console.log(hezi.join(" , ")); // 5, 9
the easier I can think of :
var hezi=[];
for (var i=0;i<GanginaA.length;i++){
hezi[GanginaA[i]] = GanginaA[i];
hezi[GanginaB[i]] = GanginaB[i];
}
hezi = hezi.filter (function(el){return el!=undefined;});
does everything in O(n) actions and not O(n^2)
Javascript's objects have hashmap like behaviour, so you can use them kind of like a set. If you iterate over all the values and set them to be keys within an object, you can use the Object.keys method to get an array of unique values out.
function uniqueValues() {
var unique = {};
[].forEach.call(arguments, function(array) {
array.forEach(function(value) {
unique[value] = true;
});
});
return Object.keys(unique);
};
This function will return the unique elements in any number of arrays, passed as arguments.
uniqueValues([1, 2, 3], [ 1, 1, 1], [2, 2, 2], [3, 3, 3]); // [ 1, 2 3 ]
One drawback to this method is that Javascript coerces all keys to strings, you can turn them back into numbers by changing the return statement to:
return Object.keys(unique).map(Number);
function randOrd() {
return (Math.round(Math.random()) - 0.5)
}
A = [0,1,2,3,4,5,6,7]
var B = A.sort(randOrd)
console.log('A=',A)
console.log('B=',B)
output:
a= [ 3, 4, 0, 1, 6, 2, 5, 7 ]
b= [ 3, 4, 0, 1, 6, 2, 5, 7 ]
I expected a to be the original array and b to be sorted. But they are both equal (sorted), why?
Because the Array.sort() method sorts in-place and then returns the array.
The Javascript sort function sorts the array in place, meaning its modifying the original array and returning it:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
Because you're running the method 'sort' on var A... which firstly will sort A into an order, and then set that data to B... which is why you get identical answers for A and B
Let's say i have an array containing (randomly) both integers and string elements:
var array = ["T", 5, 2, 9, "A"];
The possible elements, or reference, are:
var ref = ["A", "K", "Q", "J", "T", 9, 8, 7, 6, 5, 4, 3, 2];
Where A is the highest (most valuable), the K the second most valuable, and so on.
As most of you can see, this represents the diffrent cards in a deck of cards.
How should go about and sort my array above, to get the output of:
array = ["A", "T", 9, 5, 2];
Since i'm trying to learn javascript, i would prefer a pure javascript solution, but i am also wondering if there is a jQuery function for doing this task?
Here is one possible short approach:
array.sort(function(a, b) {
return ref.indexOf(a) - ref.indexOf(b);
});
N.B.: Beware that Array.prototype.indexOf method has limited browser compatibility, so use shim if required. However jQuery has its own cross browser implementation called $.inArray().
Similar to VisionN's approach, here's a way to avoid needing indexOf. I've replaced the reference array with an object literal (note: this does look kinda weird):
var array = ["T", 5, 2, 9, "A"];
var ref = {A:14, K:13, Q:12, J:11, T:10, 9:9, 8:8, 7:7, 6:6, 5:5, 4:4, 3:3, 2:2};
array.sort(function(a, b) {
return ref[b] - ref[a];
});
console.log(array);
Fiddle
Now instead of using indexOf, I use the value from array as the index into the ref object and have it return a value I can use to sort (note: I arranged the values to match the actual card numbers).