I have the following code that calculates the highest value in my set of values:
var collection = [];
$histogram.find('li').each(function() {
collection.push($(this).data());
});
component.props.collection = collection;
// Find Histogram max value
collection.hasMax = function(value) {
return this.reduce(function(prev, curr) {
return prev[value] > curr[value] ? prev : curr;
});
};
// Assign Max Value
component.props.maxRange = collection.hasMax('value').value;
I need to create a second function that does the same, but for the lowest values, e.g. the function called hasMin. I thought it would be enough to just change the comparision here:
return prev[value] < curr[value] ? prev : curr;
but I tested it and it didn't work, can you help me with that?
JavaScript's built-in Math object has a static Math.min() method, which seems to solve your problem without the need for all that code you are using.
You can get the lowest value of an array by using JavaScript's destructuring assignment (to turn the array into a comma separated list of values) and pass that list to the method.
There's also Math.max().
let myData = [1,2,3,4,5,6,7,8,9,10];
console.log(Math.min(...myData));
console.log(Math.max(...myData));
You've indicated that collection is an array of objects and each object has a value property and you need to get the lowest and highest values in that object array so this will do it:
// This is just set up to emulate your data structure. Don't add this:
var sth = "test", sth2 = "test", sth3 = "test";
let component = { props: {} };
let collection = [{value:0, label: sth},{value:1, label: sth2},{value:3, label:sth3}];
// Assuming your data structure is set up, the following will get you there:
// Loop over the array of objects, extracting the value property of each object into a new array
let vals = collection.map(function(obj){
return obj.value; // Place the value of each object into an array
});
// Just set your object's properties to the min and max of the destructured array
component.props.minRange = Math.min(...vals);
component.props.maxRange = Math.max(...vals);
console.log(component.props.minRange, component.props.maxRange);
with ES5:
let sth = "test", sth2 = "test", sth3 = "test";
let component = { props: {} };
let collection = [{value:0, label: sth},{value:1, label: sth2},{value:3,
label:sth3}];
// Assuming your data structure is set up, the following will get you there:
// Loop over the array of objects, extracting the value property of each
object into a new array
let vals = collection.map(function(obj){
return obj.value; // Place the value of each object into an array
});
// Just set your object's properties to the min and max of the destructured array
component.props.minRange = Math.min.apply(Math,vals);
component.props.maxRange = Math.max.apply(Math,vals);
console.log(component.props.minRange, component.props.maxRange);
Related
I just want to add objects inside objects dynamically using array technique. I know how do we add Objects - those are Object[key] or Object.key but suppose I thing I have to add multiple objects dymanically using function
Note: below example is just for demonstration
let array = ['first','second','third']
let object = {}
function addObject(key) {
object[key] = "someValue"
}
for (var i = 0; i < array.length; i++) {
addObject(array[i])
}
This gives output like this { first: 'someValue', second: 'someValue', third: 'someValue'}. Actually I want my output something like nested object {first:{second:{third:'somevalue'}}} not exactly this but a nested object first > second > third.
My Actual question is like how to add objects inside object in this situation. What is the correct syntax for this. Like object[first][second][third] is standard way to achieve but I can't add + operator in the left side or calling array(['first.second.third'])
`
function addObject(key) {
object[key] + [key] = "someValue"
}
or calling
array(['first.second.third'])
I'd use reduceRight to iterate over the array starting from the end. Pass in the final property value as the initial accumulator, so you get { third: 'someValue' } on the first iteration, and return it so it's the new accumulator. On subsequent iterations, do the same thing - create another object enclosing the last returned accumulator.
const array = ['first','second','third']
const nestedValue = 'someValue';
const result = array.reduceRight(
(a, prop) => ({ [prop]: a }),
nestedValue
);
console.log(result);
I am creating an object with dynamic keys as seen here:
const myObject = [
{PINO: 1764},
{FANH: 2737},
{WQTR: 1268},
{CICO: 1228}
];
I want to get the key and value with the lowest value, in this case it's {CICO: 1228}.
How I create this object is like so:
let basic = [];
_.map(values, value => {
let result = value[Object.keys(value)].reduce((c, v) => {
// sum up the amounts per key
c[Object.keys(value)] = (c[Object.keys(value)] || 0) + parseInt(v.amount);
return c;
}, {});
basic.push(result);
})
console.log(basic) => [{PINO: 1764}, {FANH: 2737}, {WQTR: 1268}, {CICO: 1228}]
How can I get the lowest number with it's key from the basic object? I tried using sort and taking the lowest number but the keys are created dynamically so I don't think I have anything I can sort against.
This is a pretty inconvenient way to store data since the keys are more-or-less useless and you need to look at the values of each object to do anything. But you can do it if you need to with something like:
const myObject = [
{PINO: 1764},
{FANH: 2737},
{WQTR: 1268},
{CICO: 1228}
];
let least = myObject.reduce((least, current) => Object.values(least)[0] < Object.values(current)[0] ? least : current)
console.log(least)
If it was a large list, you might benefit from converting the array to a different format so you don't need to keep creating the Object.values array.
Iterate the array with Array.reduce(), get the values of the objects via Object.values(), and take the one with the lower number:
const myObject = [
{PINO: 1764},
{FANH: 2737},
{WQTR: 1268},
{CICO: 1228}
];
const result = myObject.reduce((r, o) =>
Object.values(o)[0] < Object.values(r)[0] ? o : r
);
console.log(result);
I have an array object where there are key value pairs. I am trying to get the keys in that array using a loop but I am getting only 0. What is the problem with my code.
var strj = '{"name":"John","age":"30","cars":
[ {"type":"car", "year":"1998"},
{"type":"van", "year":"1995"}]}';
var myobj = JSON.parse(strj)
var care = myobj.cars.filter(c => c.type=='car');
Value of care
0:{type: "car", year: "1998"}
length:1
__proto__:Array(0)
Loop
for (var key in care){
if(care.hasOwnProperty(key)){
console.log(key)
}
}
care is a array type so you cannot do for (var key in care). You need to do for (var key in care[0]). This is because for (var key in care) will look for the key value in care and since it is a array it will always take 0 as a value in key(as you have only one object in array and its index is 0). That is why you got 0 in console.log.
var care =[{type: "car", year: "1998"}];
for (var key in care[0]){
if(care[0].hasOwnProperty(key)){
console.log(key)
}
}
care.forEach( ( singleCar ) => {
for ( var key in singleCar ){
console.log(key);
if( care.hasOwnProperty( key ) ){
console.log(key);
}
}
})
forEach will give you all the objects one by one. so you can check them.
As others have solved the issue, might i make a suggestion - Object.keys () gives an array of the keys for a given object. Since you are getting your filtered object and simply want its keys - the following will achieve that. Note that this is only using the code after you have filtered the original and have gained the "care" object.
As an aside, note that object.values() will give you an array of the values in a given object and object.entries() will give you arrays of the key / value pairing.
var care = {type: "car", year: "1998"};
var keys = Object.keys(care)
console.log(keys) // gives ["type","year"]
filter() method returns a Array of matches.
var care = myobj.cars.filter(c => c.type=='car'); // So, this returns an array.
care.forEach(element => {
console.log(Object.keys(element)); //Prints keys of each element
});
Well actually there is no problem in your code at all. But you just misunderstood the use of javascript filter. Javascript filter() creates new array that's why you are getting 0 as key. If you want to get only one matching element then find() is what you should use.
var strj = '{"name":"John","age":"30","cars":[{"type":"car", "year":"1998"},{"type":"van", "year":"1995"}]}';
var myobj = JSON.parse(strj)
var care = myobj.cars.filter(c => c.type == 'car'); // returns array
var care = myobj.cars.find(c => c.type == 'car'); // returns first matching object
var care = myobj.cars.findIndex(c => c.type == 'car'); // returns first matching index
Javascript filter() method => Read Here
Javascript find() => Read Here
Javascript findIndex() method => Read Here
In JavaScript, how would I create a two-dimensional object from a string of values, in which the first value would be the name, the last is the content, and all other values in between are properties?
For example, I have a string "capitals,Asia,China,Beijing" and I want the code to split this string into four values and create an object capitals["Asia","China"] = "Beijing";.
How could I do that?
In a complete code piece that would look like this:
<script>
Values = "capitals,Asia,China,Beijing";
Values = Values.split(",");
alert(capitals["Asia","China"]);
</script>
I want the alert box to show me the word Beijing.
How could I do that?
JavaScript does not have two-dimensional arrays or objects that you can access using array[index1, index2] as in some other languages. To do this, you have to use nested objects/arrays, such as
capitals["Asian"]["China"]
To create these, you can do something like:
function makeEntry(obj, str) {
const parts = str.split(','); // array of comma-delimited values
const value = parts.pop(); // final value ("Beijing")
const final = parts.pop(); // final property ("China")
// Find nested property, creating empty object if not there.
for (let i = 0; i < parts.length; i++) {
const part = parts[i];
if (!(parts in obj)) obj[part] = {};
obj = obj[part];
}
// Set final value.
obj[final] = value;
}
const data = {};
makeEntry(data, "capitals,Asian,China,Beijing");
console.log(data);
console.log(data.capitals["Asian"]["China"]);
This code will work even if there are more levels, such as "capitals,Asia,East Asia,China,Beijing".
Note that there is no way to create a variable in JS given a name. Therefore, we provide an initial object, and build the nest structure within it.
Another approach
Another approach is to create a single-level object with keys such as "capitals,Asian,China". That's easier to create, but might be more inconvenient to access. For example, there would be no easy way to find all the Asian capitals. Below, I'm using regexp to pick apart the input into the first part and the final value.
function makeEntry(obj, str) {
const [, key, value] = str.match(/(.*),([^,]+)$/);
obj[key] = value;
}
const data = {};
makeEntry(data, "capitals,Asian,China,Beijing");
console.log(data);
console.log(data["capitals,Asian,China"]);
You can use WeakMap to set the key of the WeakMap object to an object; Array.prototype.shift(), Array.prototype.splice(), Array.prototype.pop() to set the value of the WeakMap object instance.
let Values = "capitals,Asian,China,Beijing";
Values = Values.split(",");
const capitals = {[Values.shift()]:Values.splice(0, 2)};
const wm = new WeakMap;
wm.set(capitals, Values.pop());
console.log(wm.get(capitals));
You can alternatively set the property of an object to the result of JSON.stringify() called on Values.splice(1, 2)
let Values = "capitals,Asian,China,Beijing";
Values = Values.split(",");
const key = JSON.stringify(Values.splice(1, 2));
console.log(key);
const map = {[Values.shift()]:{[key]:Values.pop()}};
console.log(map.capitals[key]);
So, essentially I am getting a set of records as an array of objects like
[{name: tyler, categories: ["friends", "neighbor"]}, {name: joe, categories: ["friends"]}].
and I want to count the contents of the internal array instances. So in this example, the return would be friends: 2 and neighbor: 1. As some background info, I am getting a collection of records from mongo within the meteor framework. I am then using fetch() to convert these records to an array of objects like above. I then want to use these objects to create a pie graph based on the counts of the specific instances of each object within the inner array of each object (these objects would be the ones returned by the db query) within the outer array.
You can write a simple function to count your categories counts and store the result in a dictionary of key/value pairs.
function countCategories(docs){
// accumulate results inside a JS object acting as a key/value dict
var result = {};
docs.forEach(function(doc){
doc.categories.forEach(function(category){
// initialize count to 0 when a new key is found
if(_.isUndefined(result[category])){
result[category] = 0;
}
// increment the corresponding count
result[category]++;
});
});
return result;
}
Given the sample data in your question, this function will return :
Object {friends: 2, neighbor: 1}
EDIT :
You can then convert this dictionary to an array of objects.
function convertToArray(dict){
var result = [];
_.each(dict, function(value, key){
var object = {
category: key,
count: value
};
result.push(object);
});
return result;
}
Using underscore and reduce:
result = _.reduce( data, function( counter, o ) {
_.each( o.categories, function(c){
counter[c] = 1 + _.result(counter, c, 0);
});
return counter;
}, {});
Demo in this fiddle
reduce goes through your array (first arg) and applies
the function you give it (second arg) and a starting value for
the memo (third arg). This memo is passed to each call to
your function as the first argument, you can us it to store
stuff you want to remember.
I've set the starting value for the memo to be an empty object
which we will use as a counter.
result = _.reduce( data, function( counter, o ) {
// current element of the array: o
// stuff you want to remember for: counter
return counter;
}, {});
You might attach a function to the array and count the elements inside of it.
yourArray = [1,2,3];
yourArray.countElements = function(){
var elements=0;
for(x=0;this[x]!=undefined;x++){
instances++
}
return instances;
};
yourArray.countElements(); // outputs 3
Modify this, using "neighbors" and "friends" instead of "elements" and counting them only if this["categories"]["the_category"] is different of undefined.
Also you could attach it to Array.prototype