How to get lowest integer from objects in an array? - javascript

Basically what I'm trying to achieve, is the lowest integer from an object thats in an array with other objects.
r.Collection
is an array that holds 3 objects, so it looks something like this:
[{foo:"bar",abc:"xyz",number:1},{foo:"car",abc:"hcu",number:2},{foo:"tar",abc:"uif",number:3}]
Now the goal, is to sort through this array. and look at each of the number values, once it finds the lowest value. I need it to pull that entire object out of the array to use later.
Currently what i'm trying to do isn't working and i'm not sure. I could be doing this totally wrong
for (o in r.Collection) {
var data = r.Collection[o]
console.log(Math.min(data.number))
}
I know to use Math.min to find the smallest number in an array, but when I run this code, every object gets printed.
How do I sort through this array, to pull our the object with the lowest number value?

Math.min is a little to simple for this — there's no way to specify what you mean by min in an object with several values.
You can use reduce() to loop over the items in the list and keep track of the current lowest. The result will be the lowest in the list based on the function passed to reduce:
let l = [{foo:"bar",abc:"xyz",number:1},{foo:"car",abc:"hcu",number:2},{foo:"tar",abc:"uif",number:3}]
let lowest = l.reduce((lowest, item) => item.number < lowest.number ? item: lowest)
console.log(lowest)

Math.min() can work, but it would require that you use destructuring and some massaging of the array index to account for 0-base.
var r = {};
r.collection = [{foo:"bar",abc:"xyz",number:1},{foo:"car",abc:"hcu",number:2},{foo:"tar",abc:"uif",number:3}];
var min = r.collection[Math.min(...(r.collection.map(function(item){return item.number})))-1];
console.log(min);

You could also simply sort the array via Array.sort and pick the first item from it:
let data = [{foo:"car",abc:"hcu",number:2},{foo:"bar",abc:"xyz",number:1},{foo:"tar",abc:"uif",number:3}]
let result = data.sort((a,b) => a.number - b.number)[0]
console.log(result)
If you need the max simply reverse the sort by b.number - a.number etc.

Related

GoogleScript - convert arrays of different lengths into arrays of the same length

To be able to use setValues() instead of setValue on a high number of rows, I would like to know how can I convert all my arrays into arrays of the same length.
During a map function, I create one giant array that looks like this :
const myArray = [[Monday, Tuesday],[Monday,Tuesday,Wednesday],[Friday],[Monday,Friday],[Tuesday,Wednesday,Friday]] // And so on.
At the moment I use a setValue for each item of the array. The next step would be simply to use setValues(), and append an array but the problem is they are all of different lengths.
result.forEach(function(_,index){
currentSheet.getRange(1+index,5).setValue(result[index]);
});
That is going to do that for 600 lines and I will do it several times with other functions. I can live with it, but it seems like a waste. Is there a way to make the arrays homogenous (all arrays would be have a length of 3 elements, one or two being empty for example) an use one single setValues() instead ?
EDIT : the original map function to create the first array was requested. Here it is :
(Basically what it does is : it runs a map through a first array, look at the first element and go find in the source all the elements that have the same key and return the 9th and 10th elements of that array)
const result = UniquesDatas.map(uniqueRow =>
SourceDatas
.filter(row => row[0] === uniqueRow[0])
.map(row => [row[9]+" "+row[10]])
);
Thank you in advance,
Cedric
You can concat an array of empty elements of the remaining length.
const myArray = [['Monday', 'Tuesday'],['Monday','Tuesday','Wednesday'],['Friday'],['Monday','Friday'],['Tuesday','Wednesday','Friday']]
const res = myArray.map(x => x.concat(Array(3 - x.length)));
console.log(res);
As suggested by Kinglish, to get the length of the inner array with the most elements, use Math.max(...myArray.map(x=>x.length)), which will work for the more general case.

How to sort an integer keyed object by value in javascript

I have a map of id => value that I want to sort by value.
But no matter what I do, it always gets sorted by id.
Basically I have a sorted map on server side that I send to javascript via json.
{"3":"Apple","2":"Banana","1":"Orange"}
After de-serialization I get
{
1:"Orange",
2:"Banana",
3:"Apple"
}
And no matter what I try, it seems to stay in this order. Is it possible in javascript to force a non ascending sort order with interger keys?
var json = '{"3":"Apple", "2":"Banana", "1":"Orange"}';
var data = $.parseJSON(json);
for (var ix in data) {
console.log(ix + ": " + data[ix]);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
You should not rely on objects key order for these reasons.
I personally would recommend you to either use a Map, or to build an Array instead.
Below is an example to build an array from your source: for simplicity, I've added a key property to make the sorting easier.
Note: I'm using Array.from to build the array, which is taking the length from the parsed object keys length, and using the callback to init the object inline.
var json = '{"3":"Apple", "2":"Banana", "1":"Orange"}';
// Parse the json string.
const parsed = JSON.parse(json);
// Acquire the keys length
const length = Object.keys(parsed).length;
// Build an array of objects ordered in the same way it came.
const result = Array.from({length}, (_, i) => ({key: length - i, [length - i]: parsed[length - i]}));
// Log a copy of the result.
console.log(JSON.parse(JSON.stringify(result)));
// Sort ascending:
result.sort((a,b) => a.key - b.key);
// Log a copy of the sorted result.
console.log(JSON.parse(JSON.stringify(result)));
// Sort descending:
result.sort((a,b) => b.key - a.key);
// log the sorted array
console.log(result);
If you really want to rely on key orders, you can (of course), but using an array is slightly cleverer and gives no chance to have something which is not ordered as expected, unless (of course) the sorting algorithm is wrong or fails for some reason (like if key is undefined or null or not numeric in the above case).
As a final note, I'm aware that the question is about sorting an object, but because of the above reasons, I think the correct answer is just to DON'T use an object at all in that scenario specifically.

How to sort an an object in javascript by number value

I am trying to sort an object so that the property with the most votes comes first. Here's my data structure
I have found some articles on how to do this and I have created a new array and am pushing the votes value into it as well as the player object. The problem I am having is then sorting the options by the number, and removing the votes count from the array. Here's my code
var sortedOptions = [];
for (let option of options) {
sortedOptions.push(option, option.votes);
}
sortedOptions.sort(function(a, b) {
})
I have been following this but I don't understand how the sort function is working and how to do it for my purposes.
Thanks for your help :)
EDIT:
I tried doing the following code, however this was returning an object with 8 options and the object isn't sorted
sortedOptions.sort(function(a, b) {
return a.votes - b.votes;
})
Resulted in
You can use Array.prototype.sort()
The sort function takes a function as an argument, which compares two elements of the array to determine which one should be sorted where.
For your case where you want to sort based on votes you write it like so:
options.sort(function(a, b) {
// use b - a to sort descending, a - b to sort ascending
return b.votes - a.votes;
})
The for-loop you are using is strange: it produces an array which is mixed of objects and numbers, that's why the sort function doesn't work on it. Either sort on options directly, or if you need a copy use let sortedOptions = JSON.parse(JSON.stringify(options));

Using array.prototype.fill instead of array.prototype.push

I am trying to use the following prototype to fill an empty array with integers from 1-100. As per MDN's documentation:
array.prototype.fill(value, [optional start & end index])
If my understanding is correct if I call my value = 1 then if I say:
[5].fill(1); I would be left with an array with 1 sitting at all 5 index points of the array. Is there a way using .fill() to say value = 1...100? I'm beginning to think running a for loop to push values 1 - 100 might be the only way to do this, but I thought I would see if this method worked the same.
No, fill method, doesn't take a function or an iterator as an argument to change the static value with every iteration.
try this approach
var N = 100;
var arr = Array.apply(null, {length: N+1}).map(Number.call, Number);
arr.splice(0,1);
console.log(arr);
splice at the end removes the first item of the array which was 0.
If you don't want to do splice
var N = 100;
var arr = Array.apply(null, {length: N}).map(Number.call, function(item, index){ return item + 1 });
console.log(arr);
Some other good approaches are mentioned in this answer to fill values dynamically.
The fill() method fills all the elements of an array from a start index to an end index with a static value.
Therefore, it will not be possible to increment this value using the fill() method.

Iterate through array, add the sum as an object into that Array (lodash)

I'm trying to understand how to iterate through this simple array.
var data = [{"blahh":"hi","blah2":"333","third":"920","fourth":"800"}];
What I am trying to accomplish is, appending an object that is the sum of certain keys (the 'third' and 'fourth')...resulting data being this:
var data = [{"blahh":"hi","blah2":"333","third":"920","fourth":"800", "sum": "1720"}];
I imagine 'lodash' library is capable of neatly accomplishing this. I just can't figure out how to pull that off. I know this is a newbie question but perhaps answering it may helps some soul better understand lodash.
As mentioned - you don't need lodash for this. You're looking at the map function to iterate over an array and return a new array (in this case an array of objects returning a new array with objects that have a sum property) and reduce to iterate over all desired keys and sum their values. For example:
//If you want to treat numbers as numbers then use numbers.
//Some answers here are coercing strings with + - however this will result in NaN on non coerceable strings -ie 'hello',
//which will cause unexpected errors for you later (and typeof NaN is number)
var data = [{"blahh":"hi","blah2":333,"third":920,"fourth":800}];
function returnNewArrayWithSums(keys, array) {
return array.map(obj => {
obj.sum = keys.reduce((sum, key) => typeof obj[key] === 'number' ? obj[key] + sum : sum, 0);
return obj;
});
}
returnNewArrayWithSums(['third', 'fourth'], data);
edited to add - this answer is to give you a use case w/ map/reduce - ideally you wouldn't have to specify numeric keys and make this function more general for any arrays that have objects with k/v pairs that are nums that you want to sum
No need for a library to do this ... the code will likely be more complicated looking than using native methods
data.forEach(item){
item.sum = (+item.third || 0) + (+item.fourth || 0);
});
You have an array of one object - which I dont think you are trying to do. Arrays do not have a key:value pair in them (well actually they do in JavaScript but ignore that). They are an indexed list of values. You probably want to do something like this:
// notice im not putting the integer values in quotes
var data = {'blah':'hi', 'blah2':333, 'third':920, 'fourth':800 };
data.sum = data.third + data.fourth;
That will add a 'sum' field to your object with the value of the sum of third and fourth. Is this what you are trying to do?

Categories

Resources