how to custom sort an array based on its status followed by another field? - arrays

So I have an array, I need to sort it based on status in the following order i.e. failure->warn->completed.
Normally, I use lodash for sorting but its a bit of complex order here. It also needs to sort according to run after sorting with run. Im not sure how to start on this.
var arr = [{"status":"failure","name":"one","run":1},
{"status":"failure","name":"two","run":2},
{"status":"warn","name":"three","run":1},
{"status":"warn","name":"four","run":2},
{"status":"completed","name":"five","run":1}]

something like this?
Add a extra property for your sort key.
var arrnew = arr.map(function(item){
switch(item.status){
case "failure":
item.statusId=1;
break;
case "warn":
item.statusId=2;}
//...
return item} );
Sort by using that
_.sortBy(arrnew, 'statusId');

Sorts based on "status", and then the sub-slices by "run" 1 or 2:
let status_vals = [ "failure", "warn", "completed" ];
let arr = [
{"status":"failure","name":"one","run":1},
{"status":"failure","name":"two","run":2},
{"status":"warn","name":"three","run":1},
{"status":"warn","name":"four","run":2},
{"status":"completed","name":"five","run":1}
];
function sortIt ( status_arr, sort_arr ) {
let sorted_arr = [];
status_arr.forEach ( d => {
let temp = arr.filter ( obj => {
return obj.status === d;
} );
var length = temp.length;
for ( var i = 0; i < length; i++ ) {
if ( temp [ 0 ].run > temp [ i ].run ) {
temp.push ( temp.shift ( ) );
}
}
sorted_arr = [ ...sorted_arr, ...temp ];
} );
return sorted_arr;
}
sortIt ( status_vals, arr );

Related

How to get array after convert by reduce()

How to get an array after converted by reduce()?
Before convert:
After convert:
newProductsDetail = newProductsDetail.reduce((acc, curr) => {
const { categoryName } = curr
if (!acc[categoryName]) {
acc[categoryName] = []
}
acc[categoryName].push(curr)
return acc
}, [])
I would like get newProductsDetail[categoryName]
Have any way to approach this?
Thanks to all of you!
you can filter it like this
productDetail.filter( detail => { if(detail !== undefined && detail[0] !== undefined) return detail[0].categoryName === myCategory; return false; } )
Set initial value as object and not list as follows if you want to get hold of value from newProductsDetail[categoryName]:
newProductsDetail = newProductsDetail.reduce((acc, curr) => {
const { categoryName } = curr
if (!acc[categoryName]) {
acc[categoryName] = []
}
acc[categoryName].push(curr)
return acc
}, {}) // dictionary/object is initial and not list
If you only want array and some manipulation, try to use map to iterate and convert final output to array of something.

How to use apps-script to override a file with more than 10MB content?

I have a drive folder with a few g-sheet files (each larger than 100MB).
I want to override the content of the oldest file with the content of the newest file.
And then trash all files but the oldest one.
I have two problems:
Exception in file "Code".
My content can be larger than 10MB.
Is it a dead end?
function deleteOldSheets() {
var df = DriveApp.getFolderById("1haqAtxk7ZeXF9ayEbRFIf7yGi3KBu4S_");
var arr = new Array();
var files = df.getFiles();
while( files.hasNext() ) {
var f = files.next();
arr.push( [ [ f.getId() ] , [ f.getLastUpdated() ] ] );
}
if (arr.length < 2){
return;
}
arr.sort( sortFunction );
var mediaData = DriveApp.getFileById(arr[0][0]).getBlob().getDataAsString();
DriveApp.getFileById(arr[arr.length-1][0]).setContent(mediaData);
for( var i=0 ; i<arr.length-1 ; i++ ){
DriveApp.getFileById( arr[i][0] ).setTrashed( true );
}
};
function sortFunction( a , b ) {
var aDate = new Date(a[1]);
var bDate = new Date(b[1]);
if ( aDate === bDate ) return 0;
else if ( aDate < bDate ) return 1;
else return -1;
};

Construct and process multidimensional arrays/objects in ES6? (flatten/fold?)

I have:
for (const [key1, value1] of Object.entries(JSON.parse($settingsField.val()))) {
for (const [key2, value2] of Object.entries(value1)) {
for (const [key3, value3] of Object.entries(value2)) {
helper.appendRow([key1, key2, key3, value3]);
}
}
}
and to create the settings array I have
if (!result[values[0]]) {
result[values[0]] = {};
}
if (!result[values[0]][values[1]]) {
result[values[0]][values[1]] = {};
}
result[values[0]][values[1]][values[2]] = values[3];
I am trying to convert between two data structures:
{
"key_level1": {
"key_level2": {
"key_level3_1": "value1",
"key_level3_2": "value2"
}
}
}
and
[
["key_level1", "key_level2", "key_level3_1", "value1"],
["key_level1", "key_level2", "key_level3_2", "value2"]
]
First half:
function helper(o) {
this.object = (o, keys) => {
for (const [key, value] of Object.entries(o)) this[typeof(value)](value, keys.concat(key))
};
this.string = (s, keys) => console.log(s, keys);
return this.object(o, []);
}
I couldn't get it working without the {} around the for not sure what's up with that.
Second half:
function x(a, result = {}, depth = 0) {
v = a.pop();
result = depth ? {...{[v]: result}} : v;
return a.length ? x(a, result, depth + 1) : result;
}
depth is not strictly required but I found it better than Object.keys(result).length.
They are not necessarily better than the originals. In fact, they are much less maintainable.

angularjs push the values in to an object

I have the JSON object and i want to push the array values in to an JSON.
$scope.customerObjArray = ['34343434','73473333434'];
$scope.jointUsersObj = {
"branchAssociated": {
"isGridBranch": false
},
"customerNumber": ""
};
for(var i = 0; i < $scope.customerObjArray.length; i++){
$scope.jointUsersObj.customerNumber = $scope.customerObjArray[i];
}
I want the output in the following way,
{
"branchAssociated": {
"isGridBranch": false
},
"customerNumber": "34343434"
},
{
"branchAssociated": {
"isGridBranch": false
},
"customerNumber": "73473333434"
}
Well, you are doing this:
foreach number n in $scope.customerObjArray, update the property customerNumber of $scope.jointUsersObj to be n
What you actually want to do is:
foreach number n in $scope.customerObjArray, make a copy of $scope.jointUsersObj with property customerNumber to be n
try this:
$scope.jointUserObjects = [] // this is an array of users
for(var i = 0; i < $scope.customerObjArray.length; i++) {
$scope.jointUserObjects.push({
branchAssociated: {
isGridBranch: false
},
customerNumber: $scope.customerObjArray[i]
});
}
This isn't an AngularJS question at all; we can solve it with simple JavaScript. Assuming you have an array of customers and an object template, you can simply iterate over the array and map each one to an object:
const customers = [ '123', '456' ];
const template = {
branchAssociated: {
isGridBranch: false,
},
};
const mappedCustomers = customers.map( customer => {
const obj = angular.copy( template );
template.customerNumber = customer;
return obj;
});
const json = JSON.stringify( mappedCustomers );
Just declare an array and push the objects to that array.
$scope.customerObjArray = ['34343434', '73473333434'];
$scope.jointUsersObj = {
"branchAssociated": {
"isGridBranch": false
},
"customerNumber": ""
};
var jointUsersArray = [];
for (var i = 0; i < $scope.customerObjArray.length; i++) {
$scope.jointUsersObj.customerNumber = $scope.customerObjArray[i];
jointUsersArray.push($scope.jointUsersObj);
}

ExtJS - Navigate through ComboBox with prev/next buttons

I'm designing a custom control to look something like this:
I've got the ComboBox loading the Store fine, but what I'm trying to do is use the arrows to select the next and previous values in the Combo. I've set the valueField on the Combo to be the "id" from the Store, which are not incremental in fashion.
I've tried something like this:
// this gets the current record
var currentBanner = this.bannersComboBox.getStore().getById(this.bannersComboBox.getValue());
// this gets the current records index in the store
var currentStoreIndex = this.bannersComboBox.getStore().indexOf(currentBanner);
The problem is that setValue() on the ComboBox requires the "value", and in this case I need to just do a simple setValue(currentValue + 1 [-1]), or something of that nature. How would you increment the combo when the values aren't incremental?
This would be really easy if there was a selectNext() or something method on the Combo!
Figured it out. :)
var currentBanner = this.bannersComboBox.getStore().getById(this.bannersComboBox.getValue());
var currentStoreIndex = this.bannersComboBox.getStore().indexOf(currentBanner);
var nextBannerValue = this.bannersComboBox.getStore().getAt(currentStoreIndex + 1).get('id')
this.bannersComboBox.setValue(nextBannerValue);
I prefer to use select() rather than setValue(). Here's the code to select the next combobox item:
function comboSelectNextItem( combo, suppressEvent ) {
var store = combo.getStore();
var value = combo.getValue();
var index = store.find( combo.valueField, value );
var next_index = index + 1;
var next_record = store.getAt( next_index );
if( next_record ) {
combo.select( next_record );
if( ! suppressEvent ) {
combo.fireEvent( 'select', combo, [ next_record ] );
}
}
}
Code to select the previous combobox item:
function comboSelectPrevItem( combo, suppressEvent ) {
var store = combo.getStore();
var value = combo.getValue();
var index = store.find( combo.valueField, value );
var prev_index = index - 1;
var prev_record = store.getAt( prev_index );
if( prev_record ) {
combo.select( prev_record );
if( ! suppressEvent ) {
combo.fireEvent( 'select', combo, [ prev_record ] );
}
}
}
You could also extend Ext.form.field.ComboBox to include those functions (with minor changes). For example you can place this code in the launch() function of your application, so that any Ext.form.field.Combobox inherits of those two methods:
Ext.define( "Ext.form.field.ComboBoxOverride", {
"override": "Ext.form.field.ComboBox",
"selectNextItem": function( suppressEvent ) {
var store = this.getStore();
var value = this.getValue();
var index = store.find( this.valueField, value );
var next_index = index + 1;
var next_record = store.getAt( next_index );
if( next_record ) {
this.select( next_record );
if( ! suppressEvent ) {
this.fireEvent( 'select', this, [ next_record ] );
}
}
},
"selectPrevItem": function( suppressEvent ) {
var store = this.getStore();
var value = this.getValue();
var index = store.find( this.valueField, value );
var prev_index = index - 1;
var prev_record = store.getAt( prev_index );
if( prev_record ) {
this.select( prev_record );
if( ! suppressEvent ) {
this.fireEvent( 'select', this, [ prev_record ] );
}
}
}
});
Then you could use those methods anywhere in your code:
var combo = ... // the combo you are working on
combo.selectNextItem(); // select the next item
combo.selectPrevItem(); // select the previous item

Resources