Related
I just discovered lodash.js and it's freaking GREAT man, however I stumbled onto an example which had me scratching my head.
let numbers = [4, 8, 15, 16, 23, 42];
let isEven = function(n) {
return n % 2 === 0;
};
let [evens, odds] = _.partition(numbers, isEven);
// evens: [4, 8, 16, 42]
// odds: [15, 23]
According to the documentation partition creates ONE array which contains two arrays containing results which returned true or false respectively, then how the outcome of the function TWO arrays?
Because the destructuring assignment allows you to assign the first element of the returned array to variable evens, and the second to odds. Since the returned array contains two arrays, both of the variables now refer to one-dimensional arrays.
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/
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);
}
);
Is there a reason to use one over the other? It seems that _.some and _.map are easier to use or applicable to more situations (from my very limited experience) but from reading it, they sound as if they should do the same thing. I'm sure there are other instances of this and I'm all ears on learning some of the comparisons.
_.contains vs _.some
_.contains (_.contains(list, value, [fromIndex])
Returns true if the value is present in the list. Uses indexOf internally, if list is an Array. Use fromIndex to start your search at a given index.
_.some (_.some(list, [predicate], [context]))
Returns true if any of the values in the list pass the predicate truth test. Short-circuits and stops traversing the list if a true element is found.
The main difference between _.some and _.contains is that, contains checks if a given item is present in the given list and some checks if any of the elements in the list satisfies the predicate passed. So, they both are doing different tasks.
_.each vs _.map
_.each (_.each(list, iteratee, [context])
Iterates over a list of elements, yielding each in turn to an iteratee function.
_.map (_.map(list, iteratee, [context])
Produces a new array of values by mapping each value in list through a transformation function (iteratee).
_.map calls the function passed (iteratee) with each and every element of the list to create a new Array object, but _.each simply calls the function passed (iteratee) with each and every element (Note: this doesn't create an Array).
Basically _.each is the functional equivalent of for (var i = 0; i < array.length; i += 1) {...}. Again, they both are doing different jobs.
I think #thefourtheye's answer explains enough, but I thought that adding an example may help as well.
_.contains vs _.some
The big difference here is that _.contains allows you to provide a value and an index, while _.some allows you to provide a predicate.
So, for example, let's say we have an array with the first 10 numbers [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], how do we check if the array contains the number 5?
We can use the _.contains function:
_.contains([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 5); // True
We could use the _.some function as well, but it's a bit longer:
_.some([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function(num) {
return num === 5;
}); // True
But, let's say we need to check if the array contains any even number? It's hard to do that with _.contains but with _.some you could do something like this:
_.some([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function(num) {
return num % 2 === 0;
});
So yeah, there's a difference here, while _.contains is primarily used to check if an array contains a specific element, _.some could be used to check if an array contains an element with specific requirements.
_.each vs _.map
Both these loop through the entire array, but they both have a different meaning. With _.each it's quite simple, you can loop through an array:
_.each([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function(num) {
console.log(num); // Will print each number
});
The _.map function on the other hand allows you to return something, it allows you to map an array to a new array. Let's say you want an array of every number, multiplied by 2, well, you can do that with _.map:
var newCollection = _.map([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function(num) {
return num * 2;
});
console.log(newCollection); // Will contain the numbers 2, 4, 6, 8, ...
Yes, you could do that with an _.each loop as well by doing something like this:
var newCollection = [];
_.each([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function(num) {
newCollection.push(num * 2);
});
console.log(newCollection);
But _.map is just a short and easier way of doing that.
1) _.contains vs _.some
I think, it is possible to say, that _.contains is special case of _.some.
That is,
_.contains( list, value )
is a shortcut for
_.some( list, function ( el ) { return value == 3; })
The second variant is just too verbose.
In lodash such useful shortcuts presents in many functions, for example:
var users = [
{ 'user': 'barney', 'age': 36, 'active': true },
{ 'user': 'fred', 'age': 40, 'active': false }
];
_.contains({ 'user': 'fred', 'age': 40 }, 'fred');
or
_.filter(users, { 'age': 36 });
2) _.map vs _.each
These functions are just different. _.map used for collection transformation. If your input has size of N, result of _.map also has size of N. In other words, _.map is expression - use it when you need to transform each element of input collection.
_.each is just a shortcut for the for loop. It is useful, because you don't need to calculate length of array as in
for (var i = 0, len = myArray.length; i < len; i++ ) {
}
When you use _.map or _.each properly, you declare explicitly your intentions.
I'm retrieving some data and the data looks like this:
1, 2, 3, 4, 5
6, 7, 8, 9, 10
11, 12, 13, 14, 15
I want it to look like this
[
[[1],[2],[3],[4],[5]],
[[6],[7],[8],[9],[10]],
[[11],[12],[13],[14],[15]]
]
So that I may address the array like a matrix, data[0][1] would be "2".
Through this answer, it's almost there, but not quite. I'm having trouble getting to look like what I want.
How about this, assuming this accurately represents your input data:
var data = "1,2,3,4,5\n6,7,8,9,10\n11,12,13,14,15";
var matrix = data.split('\n').map(function(val) {
return val.split(',');
});
Note that your specified output is probably not what you meant. Each number should probably not be its own single-item array. Instead, the code above produces:
[
[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 1]
]
Which means matrix[0][1] would return 2, as opposed to having to do matrix[0][1][0]
Edit: As noted in the comments, I've left it up to you to ensure this fits your browser-support needs. This also goes for every other line of JS you ever write...
NOTE - If you need to iterate through an array use a simple for, and not a for..in
for..in returns the items in no guaranteed order which is probably not what you want when working with an array
for..in returns not the just the array elements, but anything added to the Array prototype (meaning if you use a traditional for loop you can be completely confident the code will work regardless of what external libraries may be included on the page. No need to worry that some other coder has added properties/methods to Array.prototype)
If \n is the line separator and , is the item seperator within a line, you can use something like:
/* assuming data is already filled like:
1,2,3,4,5
6,7,8,9,10
11,12,13,14,15
*/
var arr = data.split("\n"), arr2 = [];
for(var i = 0; i < arr.length; i++) {
if(arr[i] != '') arr2.push(arr[i].split(','));
}
console.log(arr2);
/* arr2 will be like:
[
[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15]
]
*/
var data = '1,2,3,4,5,6,7,8,9,10,11,12,13,14,15'.split(',');
var matrixData = [];
while (data.length > 0) {
matrixData.push(data.splice(0, 5));
}
document.write(matrixData[0][1]);
Edit: If you get the data as a simple array of numbers