I want to sort a Array in custom way
Given arary:
arry = [0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,18,21,21,22,22,23,23]
Expected output:
[21,22,22,23,23,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,16,16,17,17,18]
You could check the value first and the sort number greater than 20 first.
var array = [0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 21, 21, 22, 22, 23, 23],
predicate = function (v) { return v > 20; };
array.sort(function(a, b) {
return predicate(b) - predicate(a) || a - b;
});
console.log(array);
Related
I am trying to filter these Javascript objects:
A= [{
asset_bubble: 17,
biodiversity_loss: 15,
code: "CH",
critical_information: 14,
cyber_attacks: 19,
data_fraud: 13,
deflation: 4,
energy: 18,
extreme_weather: 12,
change_adaptation: 9,
infrastructure: 33
},
{
asset_bubble: 4,
biodiversity_loss: 7,
code: "TZ"
critical_information: 9,
cyber_attacks: 9,
data_fraud: 10,
deflation: 3,
energy: 1,
extreme_weather: 2,
change_adaptation: 7
infrastructure: 3
}]
By this array:
array=["data_fraud","change_adaptation", "deflation","code"]
The result I am looking for is:
B= [{ code: "CH",
data_fraud: 13,
deflation: 4,
change_adaptation: 9
},
{
code: "TZ"
data_fraud: 10,
deflation: 3,
change_adaptation: 7
}]
I have done this:
B = A.map(({ ...array }) => ({ ...array }))
But this is not working. I know map should do the work but how can I list the fields of the objects I want to filter out?
Inside Array.map callback, you can map array variable values to [key, item[key]] pair and from that 2d array, you can generate the object using Object.fromEntries as follows.
const A = [{
asset_bubble: 17,
biodiversity_loss: 15,
code: "CH",
critical_information: 14,
cyber_attacks: 19,
data_fraud: 13,
deflation: 4,
energy: 18,
extreme_weather: 12,
change_adaptation: 9,
infrastructure: 33
}, {
asset_bubble: 4,
biodiversity_loss: 7,
code: "TZ",
critical_information: 9,
cyber_attacks: 9,
data_fraud: 10,
deflation: 3,
energy: 1,
extreme_weather: 2,
change_adaptation: 7,
infrastructure: 3
}];
const array = ["data_fraud","change_adaptation", "deflation","code"];
const B = A.map((item) => (
Object.fromEntries(array.map((key) => ([key, item[key]])))
));
console.log(B);
Here's another approach, using reduce:
const A= [ {
asset_bubble: 17,
biodiversity_loss: 15,
code: "CH",
critical_information: 14,
cyber_attacks: 19,
data_fraud: 13,
deflation: 4,
energy: 18,
extreme_weather: 12,
change_adaptation: 9,
infrastructure: 33
},
{
asset_bubble: 4,
biodiversity_loss: 7,
code: "TZ",
critical_information: 9,
cyber_attacks: 9,
data_fraud: 10,
deflation: 3,
energy: 1,
extreme_weather: 2,
change_adaptation: 7,
infrastructure: 3
}];
const array=["data_fraud","change_adaptation", "deflation","code"];
const B = A.map(item => array.reduce((acc, key) => ({ ...acc, [key]: item[key]}), {}));
console.log(B);
B = A.map(({ code, data_fraud, deflation, change_adaptation }) => ({ code, data_fraud, deflation, change_adaptation }))
I think this should work?
based on Derek's answer I made handy function to filter object by its keys:
function filterBykeys ( target, keyList ) {
return Object.fromEntries(
Object.entries(target).filter(
([key,value]) => keyList.includes(key)
)
)
}
and here is a snippet using this function
function filterBykeys ( target, keyList ) {
return Object.fromEntries(
Object.entries(target).filter(
([key,value]) => keyList.includes(key)
)
)
}
const data= [{
asset_bubble: 17,
biodiversity_loss: 15,
code: "CH",
critical_information: 14,
cyber_attacks: 19,
data_fraud: 13,
deflation: 4,
energy: 18,
extreme_weather: 12,
change_adaptation: 9,
infrastructure: 33
},
{
asset_bubble: 4,
biodiversity_loss: 7,
code: "TZ",
critical_information: 9,
cyber_attacks: 9,
data_fraud: 10,
deflation: 3,
energy: 1,
extreme_weather: 2,
change_adaptation: 7,
infrastructure: 3
}];
const arrays=["data_fraud","change_adaptation", "deflation","code"];
const result = data.map( obj => {
return filterBykeys(obj, arrays);
});
console.log(result)
If my Array1 is
Array1 = [1,2,3,4,5,6,7,8,9,10]
the Result should be the same as Combined_Array= [1,2,3,4,5,6,7,8,9,10]
if i got
Array2=[11,12,13,14,15,16,17,18,19,20]
the Resut should be Combined_Array =[1,2,3,4,5,11,12,13,14,15]
and if again i got
Array3=[21,22,23,24,25,26,27,28,19,30]
The Combined_array = [1,2,3,11,12,13,21,22,23,24]
and so on , Doesnt matter how much Array's i want that it should give me a Combined_Array from all the different Array with Fixed Length
Need a Function to make this work .
You could take a closure over the collected arrays and retuen an array of the parts which are difined by the count of arrays.
const
getCombined = (a) => {
const allArrays = [];
return (b => {
allArrays.push(b);
let i = 0,
p = Math.floor(10 / allArrays.length),
result = [];
while (i < allArrays.length) result.push(...allArrays[i++].slice(0, p));
while (result.length < 10) result.push(allArrays[allArrays.length - 1][p++]);
return result;
});
};
var c = [],
add = getCombined(c);
c = add([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
console.log(...c); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
c = add([11, 12, 13, 14, 15, 16, 17, 18, 19, 20]);
console.log(...c); // [1, 2, 3, 4, 5, 11, 12, 13, 14, 15]
c = add([21, 22, 23, 24, 25, 26, 27, 28, 29, 30]);
console.log(...c); // [1, 2, 3, 11, 12, 13, 21, 22, 23, 24]
You need to consider many corner cases (if result array length exceeds given arrays count, if given arrays length differs and so on).
This will work for the simple scenario:
const arr1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const arr2 = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
const arr3 = [21, 22, 23, 24, 25, 26, 27, 28, 19, 30];
const combineArrays = (arr, length) => {
let elementsCount = Math.floor(length / arr.length);
const result = arr.reduce((acc, el) =>
acc.concat(el.slice(0, elementsCount)), []);
while (result.length < length)
result.push(...arr.pop().slice(elementsCount, ++elementsCount));
return result;
};
const result1 = combineArrays([arr1], 10); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const result2 = combineArrays([arr1, arr2], 10); // [1, 2, 3, 4, 5, 11, 12, 13, 14, 15]
const result3 = combineArrays([arr1, arr2, arr3], 10); // [1, 2, 3, 11, 12, 13, 21, 22, 23, 24]
My purpose is to create a function that removes elements from an array to reduce its length to the desired length.
But the condition is that it should remove the elements at (almost) equal interval. And the function should work for any value of array.length and desired_length.
For example:
myArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19];
desired_length = 7;
myFunction( myArray, desired_length ) //returns [0, 4, 7, 10, 13, 16, 19]
It does not matter which elements are removed. But if we plot the elements of returned array on a line chart, then the line should be as smooth as possible.
Use Case:
I have an array which contains images. I want to render them as GIF of fixed number of frames. So if there are 100 images in the array, I want to remove some images from between so the array has only 20 images. Now the important part is to remove frames at equal interval so the final animation is as little jerky as possible. The length of the array can vary each time.
You could use the remainder operator and check for zero with the division of the length of the aaray and the wanted length.
function getArray(array, length) {
return array.filter(function (_, i, a) {
return !(i % (a.length / length));
});
};
var myArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19];
console.log(getArray(myArray, 10)); // [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
console.log(getArray(myArray, 5));
.as-console-wrapper { max-height: 100% !important; top: 0; }
The important thing is the calculation of step which can be used to iterate over the original array.
EDIT: adding Math.round makes the code work for length / desired_length != 0. Your desired output is hard to reproduce in my eyes.
myArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
console.log(myFunction( myArray, 10 )) // [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
console.log(myFunction( myArray, 5 )) // [0, 4, 8, 12, 16]
console.log(myFunction( myArray, 7 )) // [0, 3, 6, 9, 12, 15, 18]
function myFunction( arr, desired_length) {
var arr_length = arr.length;
var step = Math.round(arr_length / desired_length);
var new_arr = [];
for (var i = 0; i < arr_length; i += step) {
new_arr.push(arr[i]);
}
return new_arr;
}
Solution:
// always saves first and last element
function setMaxElements( array, max_elements ) {
if( array.length > max_elements ) {
// Always save first element
var new_array = [ array[0] ];
// index of last saved element
var last_saved_element = 0;
for( var i = 1; i < array.length; i++ ) {
// (array.length-1) & (max_elements-1) because we already saved one element
var element_group = Math.floor( i / ( array.length - 1 ) * ( max_elements - 1 ) );
if( last_saved_element < element_group ) {
new_array.push( array[i] );
last_saved_element = element_group;
}
}
return new_array;
} else {
return array;
}
}
myArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19];
console.log( setMaxElements( myArray, 13 ) ); // [0, 2, 4, 5, 7, 8, 10, 12, 13, 15, 16, 18, 19]
console.log( setMaxElements( myArray, 10 ) ); // [0, 3, 5, 7, 9, 11, 13, 15, 17, 19]
console.log( setMaxElements( myArray, 07 ) ); // [0, 4, 7, 10, 13, 16, 19]
console.log( setMaxElements( myArray, 03 ) ); // [0, 10, 19]
For my use case I decided to keep the first and last element and remove from the rest. If that is not a constraint for you, then you can also use this function:
// always saves first element but may remove the last element
function setMaxElements( array, max_elements ) {
if( array.length > max_elements ) {
var new_array = [];
var last_saved_element = -1 ;
for( var i = 0; i < array.length; i++ ) {
var element_group = Math.floor( i / array.length * max_elements );
if( last_saved_element < element_group ) {
new_array.push( array[i] );
last_saved_element = element_group;
}
}
return new_array;
} else {
return array;
}
}
myArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19];
console.log( setMaxElements( myArray, 13 ) ); // [0, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19]
console.log( setMaxElements( myArray, 10 ) ); // [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
console.log( setMaxElements( myArray, 07 ) ); // [0, 3, 6, 9, 12, 15, 18]
console.log( setMaxElements( myArray, 03 ) ); // [0, 7, 14]
I put the values in excel to understand how to create the formula.
Final result
As you can see, The function converts the array of any length to the desired length.
I'm trying to understand where i'm going wrong here. say I have an array:
result = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
I want to get rid of every 6 entries in my array, leave the 7th there, and go one. In effect i'm hoping to get rid of 6/7th of the values in my array. I'm thinking splice() could be perfect for that, but somehow the code below doesn't seem to work. Any suggestions?
Many thanks to you all!
function random_select ()
{
for(var i=0; i < result.length; i+7)
{
result.splice[i,6];
}
};
Try this instead:
var result = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
for (var i = 0; i < result.length; i++) result.splice(i, 6);
This will:
First remove [0, 1, 2, 3, 4, 5], and let [6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] be.
Next remove [7, 8, 9, 10, 11, 12] and let [13, 14, 15, 16] be.
Finally remove [13, 14, 15, 16].
Hence the result is [6, 13]. Is this what you want?
Let's say I have the follow:
var test_data = {
'numGroup1': [[(1, 2, 3, 4, 5), (5, 6, 7, 8, 9)]],
'numGroup2': [[(10, 11, 12, 13, 14), (15, 16, 17, 18, 19)]],
};
How would I go about iterating through it using JavaScript?
var test_data = {
'numGroup1': [[1, 2, 3, 4, 5], [5, 6, 7, 8, 9]],
'numGroup2': [[10, 11, 12, 13, 14], [15, 16, 17, 18, 19]],
};
for(var key in test_data){
group = test_data[key];
for(var num in group){
console.log(group[num]);
}
}
#Ian is right... using () will not do anything but enter the last digit of each group. You should use a multidimensional array
'numGroup1': [[1, 2, 3, 4, 5], [5, 6, 7, 8, 9]],
'numGroup2': [[10, 11, 12, 13, 14], [15, 16, 17, 18, 19]],
You can use underscorejs to iterate over it
var test_data = {
'numGroup1': [[1, 2, 3, 4, 5], [5, 6, 7, 8, 9]],
'numGroup2': [[10, 11, 12, 13, 14], [15, 16, 17, 18, 19]],
};
_.chain(test_data).map(function(value, key) {
return value;
}).flatten().each(alert);