Finding the maximum property under a value - javascript

I have a list of objects, each with its properties.
I am trying to find a specific object in this list with this .find although I can't figure out how to find the maximum value of one of it's properties under a certain value.
let x = this.state.pricing_adjustments_view.filter((e) => {
return e.location_id === this.state.selectedLocation,
e.car_model_id === this.state.selectedCar,
moment(e.calendar_day).isSame(this.state.from, "day"),
_.max(e.minimum_duration) <= duration
})
Here it's the e.minimum_duration. I want to find the biggest value, but that is under "duration"
I am trying it with "lodash", here represented by the "_".
I am open to other possibilities.
this.state.pricing_adjustments_view is an array of objects, and you could say that for each object, the "UNIQUE" key is its "location_id", "car_model_id", "calendar_day" and "minimum_duration".
So there are several objects that are the same if we only consider "location_id", "car_model_id", "calendar_day", and then they have different "minimum_duration". I need to get the one that has the highest "minimum_duration".

Ok,
You say it's the minimum_duration that interests you. In order to find the biggest (or smallest..) It's simple to just order pricing_adjustments_view by minimum_duration and take it's highest value.
So you can basically do following using lodash lib.
// sort dataa..
let sorted = _.sortBy(this.state.pricing_adjustments_view, 'minimum_duration');
// take last in list!
let has_highest_minimum_duration = sorted[sorted.length-1];

Related

Prevent pushing to array if duplicate values are present

I'm mapping an array and based on data i'm pushing Option elements into an array as follows
let make_children: any | null | undefined = [];
buyerActivityResult && buyerActivityResult.simulcastMyAccount.data.map((item: { make: {} | null | undefined; }, key: any) => {
make_children.push(
<Option key={key}>{item.make}</Option>
);
});
Following data array has several objects and these objects have an attribute called model.
buyerActivityResult.simulcastMyAccount.data
I want to prevent pusing Options to my array if the attribute model has duplicate data. It only has to push once for all similar model values.
How can i do it?
I tried something like this
buyerActivityResult && buyerActivityResult.simulcastMyAccount.data.map((item: { model: {} | null | undefined; }, key: any) => {
model_children.indexOf(item.model) === -1 && model_children.push(
<Option key={key}>{item.model}</Option>
);
});
But still duplicate values are being pushed into my array.
Its difficult to tell what you are trying to achieve but it looks like a map may not be the right tool for the job.
A map returns the same sized length array as that of the original array that you are calling map on.
If my assumptions are correct, your buyerActivityResult.simulcastMyAccount.data array has duplicate values, and you want to remove these duplicates based on the model property? One way to achieve this would be to use the lodash library for this, using the uniq function:
const uniqueResults = _.uniq(buyerActivityResult.simulcastMyAccount.data, (item) => item.model);
The Array.prototype.map() method is supposed to be used for manipulating the data contained into the array performing the operation. To manipulate data from other variables I recommend to use a for-loop block.
If item.model is an object, the function Array.prototype.indexOf() always returns -1 because it compares the memory address of the objects and does not do a deep comparison of all properties values.
The usual solution to remove duplicate data from an array is converting the Array into a Set then back to an Array. Unfortunately, this works only on primary type values (string, number, boolean, etc...) and not on objects.
Starting here, I will review your source code and do some changes and explain why I would apply those changes. First of all, assuming the make_children array does not receive new attribution later in your code, I would turn it into a constant. Because of the initialization, I think the declaration is overtyped.
const make_children: any[] = [];
Then I think you try to do too much things at the same time. It makes reading of the source code difficult for your colleagues, for you too (maybe not today but what about in few weeks...) and it make testing, debugging and improvements nearly impossible. Let's break it down in at least 2 steps. First one is transforming the data. For example remove duplicate. And the second one create the Option element base on the result of the previous operation.
const data: { make: any }[] = buyerActivityResult?.simulcastMyAccount?.data || [];
let options = data.map((item) => !!item.model); // removing items without model.
// Here the hard part, removing duplicates.
// - if the models inside your items have a property with unique value (like an ID) you can implement a function to do so yourself. Take a look at: https://stackoverflow.com/questions/2218999/remove-duplicates-from-an-array-of-objects-in-javascript
// - or you can use Lodash library like suggested Rezaa91 in its answer
options = _.uniq(data, (item) => item.model);
Now you only have to create the Option elements.
for (var i = 0; i < options.length; i++) {
model_children.push(<Option key={i}>{options[i].model}</Option>);
}
// OR using the Array.prototype.map method (in this case, do not declare `model_children` at the beginning)
const model_children:[] = options.map((opt:any, i:number) => <Option key={i}>{opt.model}</Option>);
Despite the lack of context of the execution of the code you provided I hope my answer will help you to find a solution and encourage you to write clearer source code (for the sake of your colleagues and your future self).
PS: I do not know anything about ReactJs. forgive me my syntax mistakes.

How to get lowest integer from objects in an array?

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.

Google Scripts 2D Array sorting by value

I have a 2d array that I am attempting to sort.
The array is typically accessed with this structure: array[r][c].
I want to re-order the values of array, so that each [r] value is sorted by the 4th c value.
Looking online, I've seen a few sorting scripts that seem to work for other structured arrays, but I'm wondering if i'm missing something stupid.
The array is structured so that for each 'r' value in array, there is a list of values, depending on what 'c' value you put in (eg: if you do array[0][2] that will be the first entry's address, and array[0][10] is the first entry's phone number).
I want to be able to sort based off of c values 4 and... 10 (for example). (ideally, I'd sort by multiple columns, such as sort by last name first, then by first name--but i'll settle for one sort for now hahaha )
I'm not certain if any of the default sort functions would work for me, or if i need to write out a manual sort function (which i'm hoping i do not have to do as that would be fairly inefficient).
Thanks for any pointers
You'll need to write your own compare function.
Snippet:
const COLTOSORT = 2;
function compare(row1, row2) {
return row1[COLTOSORT] < row2[COLTOSORT]
? -1
: row1[COLTOSORT] > row2[COLTOSORT]
? 1
: 0;
}
array.sort(compare);
References:
Array#sort

object access vs array access in javascript

I have a series of data and the size of it increases gradually. I want to find a specific row of my data with its Id. I have two options. first: create an array and push every new row to this array and every time I want a row just search through items in the array or use array prototype function (find). the other option is to create an object and every time a new row comes just add this row as a property (and the property name would be the Id of the row). and when I want to find a row just get the property of this object by its name(Id). Now I want to know which option is the most efficient way? (or is there a third option?)
first option:
const array = [
{
"Id":15659,
"FeederCode":169,
"NmberOfRepetition":1
},
{
"Id":15627,
"FeederCode":98,
"NmberOfRepetition":2
},
{
"Id":15557,
"FeederCode":98,
"NmberOfRepetition":1
}
]
each time a new row comes a new is pushed into this array.
access : array.find(x => x.Id === 15659)
second option:
const object = {
15659:{
"Id":15659,
"FeederCode":169,
"NmberOfRepetition":1
},
15627:{
"Id":15627,
"FeederCode":98,
"NmberOfRepetition":2
},
15557:{
"Id":15557,
"FeederCode":98,
"NmberOfRepetition":1
}
}
each time a new row comes a new property is added to this object.
access : object[15659]
edit: I read somewhere that adding new properties to existing object has too much cost.
In case you are looking forward to perform search operation then you should use Object as it gives better performance as compared to search in Array.
Complexity of search in Object is O(1) and in Array is O(n). Hence, to yield better performance, you should use Object.
Well in the first example you will have to iterate the array every time, when using Find.
In the second example you will be accessing a property directly, leading to O(1) execution time, always fixed, no matter how many items are in there. So for better performance you ought to go by your 2nd way
Reading from objects is faster and takes O(1) time, like #NikhilAggarwal Just said.
But recently I was reading about V8 optimizations and wanted to check, so used benchmark js for confirmation.
Here are my findings -
Number of entries in obj or arr : 100000
Number of fetch operations from Obj: 47,174,859 ops/sec
Number of search operation from Array: 612 ops/sec
If we reduce the entries - The number of operations for object almost remains the same but increases exponentially for arrays.
Number of entries in obj or arr : 100
Number of fetch operations from Obj: 44,264,116 ops/sec
Number of search operation from Array: 520,709 ops/sec
Number of entries in obj or arr : 10
Number of fetch operations from Obj: 46,739,607 ops/sec
Number of search operation from Array: 3,611,517 ops/sec

Fast find for indices by ID

I have million of objects each have an unique ID - number.
Each object for making it simple contains name
They objects are being added into array.
Into this array i'm adding and removing objects.
In order to remove object I have the id, and then need to find the index in the array and splice it out.
In my case i have allot of objects and can have allot of removes operations. so in case i have 1000 removes. and all of this objects ids are stored in the end of the array, than i will run over the all 1 million objects till i find them.
Storing the index in the object after adding is not good, because every each remove i need to update the indices of all objects stored after the removed one.
For example removing the first 1000 will cause updating the rest of the 1M-1000 items indices.
My question is, what is the best solution for my problem?
-- UPDATE --
for example: My flat array look like this after adding 1M objects
[ obj1, obj2, obj3, .... obj1000000 ]
I want to remove now the object obj1000000. For finding which index this object
was inserted to i need to run over all the array (or till i found the item) and compare the current item id with my obj1000000 id, and break out from the loop when found. Then remove the item by it's index.
If i would store the index of each object in the object itself after it being added to the array, i would have to update the rest of the objects indices after removing one.
For example: obj1 will contains property index=0, obj2 will have index=1 and so on. To remove obj5 i just get its property index which is 4 and remove it. but now obj6 which has index=5 is incorrect. and should be 4. and obj7 should be 5 and so on. so update must be done.
My SmartArray holds an TypedArray created in some size. And i'm expending it if needed. When push is called. I'm simply set the value in the last item this._array[this.length++] = value; (Checking of course if to expand the array)
SmartArray.prototype.getArray = function () {
return this._array.subarray(0, this.length);
}
SmartArray.prototype.splice = function (index, removeCount) {
if (index + removeCount < this.length) {
var sub = this._array.subarray(index + removeCount, this.length);
this._array.set(sub, index);
} else {
removeCount = this.length - index;
}
this.length -= removeCount;
}
It is working very fast, subarray doesn't create a new array. And set is working very fast as well.
The standard solutions for this problem are
balanced (binary) trees,
hash tables.
They take respectively O(Log(N)) and O(1) operations per search/insertion/deletion on average.
Both can be implemented in an array. You will find numerous versions of them by web search.

Categories

Resources