Sorting object property by key array - javascript

If I have a JavaScript object such as:
const group = {
Gp1: 1,
Gp12:1,
Gp11:2,
Gp10: 0,
Gp2: 1,
Gp5: 4,
Gp3: 4,
Gp4: 4,
Gp6: 4,
};
I want to make sortable ascending by key of the array
with this code
const sortable = Object.fromEntries(
Object.entries(group).sort(([,a],[,b]) => a-b)
);
console.log(sortable);
I end up with
{
Gp1: 1,
Gp10: 0,
Gp11: 2,
Gp12: 1,
Gp2: 1,
Gp3: 4,
Gp4: 4,
Gp5: 4,
Gp6: 4
}
Is there a way to sort the properties based on key array? So that I end up with
{
Gp1: 1,
Gp2: 1,
Gp3: 4,
Gp4: 4,
Gp5: 4,
Gp6: 4,
Gp10: 0,
Gp11: 2,
Gp12: 1,
}

You can use string#localeCompare to sort based on numeric value by passing {numeric: true}.
const o = { Gp1: 1, Gp10: 0, Gp11: 2, Gp12: 1, Gp2: 1, Gp3: 4, Gp4: 4, Gp5: 4, Gp6: 4 },
result = Object.fromEntries(Object.entries(o).sort((a,b) => a[0].localeCompare(b[0], undefined, {numeric: true})));
console.log(result);

Are you finding something like this?
const sortable = Object.fromEntries(
Object.entries(group).sort(([a,],[b,]) => parseInt(a.replace('Gp', '')) - parseInt(b.replace('Gp', '')))
);

Related

How to create dynamic array filter expression?

I need a function to filter array of objects based on given structure of object. So I have this object:
{
"2": [
{
"fd_id": 16,
...others
}
],
"3": [
{
"fd_id": 2,
...others
},
{
"fd_id": 3,
...others
}
]
}
I would like to filter another array based on this object. Like this;
const result = products.filter(item => {
// returns array of numbers [1, 2, 3]
const filters = item.filters;
if(filters){
// Here must be refactored
return ((filters.includes(givenObj[2][0].fd_id))
&& (filters.includes(givenObj[3][0].fd_id) || filters.includes(givenObj[3][1].fd_id)));
}
});
But this function must be dynamic. Because the input object may change. So for between each parent "&&", and between each children "||" condition must be applied. Thanks for any help. This is the link to example https://jsfiddle.net/cadkt86n/
A function to loop the data will help.
My Logic
Generate the list of fd_ids from the groups using Array.map
Filter products array. Check for the matching combination in filters node of products array. Condition is there should be a matching combination in each nodes of fdIdList array.
Working Fiddle
var groups = {
"2": [
{ "fd_id": 16, "fd_fRef": 2, "fd_ad": "35 - 50", "fd_siraNo": 255, "checked": true }
],
"3": [
{ "fd_id": 2, "fd_fRef": 3, "fd_ad": "KURU", "fd_siraNo": 255, "checked": true },
{ "fd_id": 3, "fd_fRef": 3, "fd_ad": "KARMA", "fd_siraNo": 255, "checked": true }
]
}
// Aggregates the list of fd_id s - This wil be an array of arrays
// [[16],[2,3]] => This will be the value
const fdIdList = Object.values(groups).map(a => a.map(b => b.fd_id));
var products = [
{
"id": 1,
"filters": [2, 3, 4, 13, 16, 17, 18, 19, 31, 48, 309, 318],
},
{
"id": 2,
"filters": [2, 3, 4, 13, 15, 17, 18, 19, 31, 48, 309, 318],
}
];
// Check if there is a common element in each node of fdIdList
var result = products.filter(item => {
const filters = item.filters;
if (filters) {
let isFound = true;
fdIdList.forEach(idListNode => {
isFound = isFound && idListNode.filter(value => filters.includes(value)).length > 0;
})
return isFound
}
});
console.log(result)

How to filter an array and return new array of objects with indexed values?

Given the array const vals = [1, 2, 3, 4, 5, 6, 7, 8, 9];
How can I filter and return a new array of indexed key/value pair objects for example:
const vals = [1, 2, 3, 4, 5, 6, 7, 8, 9];
// My fail attempt using filter()
let obj = vals.filter((n, i) => {
return new Object({ i: n % 2 });
});
return obj;
// expected result [{1:2}, {3:4}, {5:6}, {7:8}]
I need to keep the index values as I will filter 2 different arrays with different criteria and associated them later.
Update
Second attempt using map() as suggested in the comments
let obj = vals.map((n, i) => {
if (n % 2) {
return { [i]: n };
}
});
Gives me the following:
[{0:1}, undefined, {2:3}, undefined, {4:5}, undefined, {6:7}, undefined, {8:9}]
To get a list of { key: value } objects where key is the index, and the values are only even without the odd values, you can do this:
const vals = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const result = vals.map((v, i) => [i, v])
.filter(([_, v]) => v % 2 == 0)
.map(([i, v]) => ({ [i]: v }));
console.log(result);
With the first map, you make a list of [[0, 1], ...] pairs to save the index for later.
Then you filter your index-value pairs so only even values remain.
Then you pack those pairs into an object in another map.
This can be done more efficiently with a single iteration using reduce:
const vals = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const result = vals.reduce((a, v, i) => {
if (v % 2 == 0) {
a.push({ [i]: v });
}
return a;
}, []);
console.log(result);
Youn can try simple for loop or the reduce function
let arr = [];
for(let i = 0; i<vals.length-1;i += 2)
{
let obj={};
obj[vals[i]]=vals[i+1];
arr.push(obj);
};

Get element from math.matrix in Javascript

I'm using the matrix element from the math.js library.
I create a matrix:
let eye = math.matrix([
[1, 0, 0],
[0, 1, 0],
[0, 0, 1]
]);
But when I try to access an element of the matrix, it is always undefined.
console.log(eye[0][0]) -> undefined
console.log(eye[0]) -> undefined
Any suggestions? I have read through the documentation for the math.js library and I see nothing about how to access an individual element.
And I do need to use this library, as I am doing matrix-based operations (matrix multiplication).
If you print out eye, you get the following object.
{
_mathjs: "DenseMatrix",
_data: [
[ 1, 0, 0 ],
[ 0, 1, 0 ],
[ 0, 0, 1 ]
],
_size: [ 3, 3 ]
}
But that is just the internal structure used to hold information about the matrix, you need to call helper methods as seen in the docs.
https://mathjs.org/docs/reference/functions/subset.html
https://mathjs.org/examples/matrices.js.html
If you want to access the data, you can always interrogate the internal matrix data directly. This is a bad idea, because the fields are all treated as private; internal fields (start with an underscore).
const __print = (x) => console.log(JSON.stringify(x));
let eye = math.matrix([
[1, 0, 0],
[0, 1, 0],
[0, 0, 1]
]);
__print(eye._data[0][0]); // 1
__print(eye._data[0]); // [1, 0, 0]
__print(eye._data[1]); // [0, 1, 0]
__print(eye._data[2]); // [0, 0, 1]
.as-console-wrapper { top: 0; max-height: 100% !important; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/8.1.1/math.js"></script>
It is recommended that you use the helper methods which are available in the library.
Note: After fine-tuning my response, I found a similar method of retrieving a row in the Issue #230 on GitHub.
You need to figure out the number of columns in the matrix. After that, you can grab a subset starting at the desired row index with a range of 0 to the number of columns in the row. The result must then be flattened.
const __print = (x) => console.log(JSON.stringify(x));
let eye = math.matrix([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]);
const __row = (m, r) =>
(([ rows, cols ]) => math.flatten(math.subset(m,
math.index(r, math.range(0, cols))).valueOf()))
(m.size());
const __col = (m, c) =>
(([ rows, cols ]) => math.flatten(math.subset(m,
math.index(math.range(0, rows), c)).valueOf()))
(m.size());
const __cell = (m, r, c) =>
math.subset(m, math.index(r, c));
__print(__cell(eye, 0, 0)); // 1
__print(__row(eye, 0)); // [1, 2, 3]
__print(__row(eye, 1)); // [4, 5, 6]
__print(__row(eye, 2)); // [7, 8, 9]
__print(__col(eye, 0)); // [1, 4, 7]
__print(__col(eye, 1)); // [2, 5, 8]
__print(__col(eye, 2)); // [3, 6, 9]
.as-console-wrapper { top: 0; max-height: 100% !important; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/8.1.1/math.js"></script>
Turns out that they are already implemented, but you still need to flatten the result.
const __print = (x) => console.log(JSON.stringify(x));
let eye = math.matrix([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]);
const __row = (m, r) =>
math.flatten(math.row(m, r).valueOf());
const __col = (m, c) =>
math.flatten(math.column(m, c).valueOf());
const __cell = (m, r, c) =>
math.subset(m, math.index(r, c));
__print(__cell(eye, 0, 0)); // 1
__print(__row(eye, 0)); // [1, 2, 3]
__print(__row(eye, 1)); // [4, 5, 6]
__print(__row(eye, 2)); // [7, 8, 9]
__print(__col(eye, 0)); // [1, 4, 7]
__print(__col(eye, 1)); // [2, 5, 8]
__print(__col(eye, 2)); // [3, 6, 9]
.as-console-wrapper { top: 0; max-height: 100% !important; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/8.1.1/math.js"></script>
You might want to try to combine both subset and index to get the value at the index.
Source: mathjs
math.subset(eye, math.index(0, 0)) // 1
math.subset(eye, math.index(0, 1)) // 0
You are trying to reach content of eye as if eye is 2 dimensional js array, which is definitely not true. math.matrix returns some object, the best way to investigate it's structure is console.log(eye) (in Chrome or other modern browser). Or/and read docs about it methods

how to sort an array of numbers in javascript making sure that the first count finished before adding duplicates?

I have this array of numbers that i am working with that currently look this;
count = [1,4,3,1,2,3,4,5,6,2,3,5,7];
How can i transform and sort it to make it look like this;
count = [1,2,3,4,5,6,7,1,2,3,3,4,5];
Please help, any idea out there on how to approach this?
1) Get unique elements and sort
2) Get remaining elements and sort
3) combine (1) and (2) arrays.
count = [1, 4, 3, 1, 2, 3, 4, 5, 6, 2, 3, 5, 7];
const spSort = arr => {
const uniq = [...new Set([...arr])];
const rem = [];
const temp_set = new Set([...arr]);
arr.forEach(x => {
if (temp_set.has(x)) {
temp_set.delete(x);
} else {
rem.push(x);
}
});
return [...uniq.sort(), ...rem.sort()];
};
console.log(spSort(count));
Use a Set to create unique numbers and a hash object to keep count of duplicates:
const count = [1, 4, 3, 1, 2, 3, 4, 5, 6, 2, 3, 5, 7];
const hash = count.reduce((obj, num) => {
obj[num] = obj[num] ? ++obj[num] : 1;
return obj;
}, {});
const uniq = [...new Set(count)].sort();
uniq.forEach((num, _, arr) => {
while (--hash[num]) arr.push(num);
});
console.info(uniq);

Finding string element in array with integers using lodash includes not working

Here's my code, i'm using vuejs:
pins: [1, 2, 3, 4, 5, 6, 7, 8, 9, 0], //my data
isThisPin(pin){
return _.includes(this.pins, pin);
}
console.log(this.isThisPin('X')); //it returns true
Basically i'm trying to guess if the selected pin is not included in the pins, I expect to return it as false, but it just keep returning as true.
Am I using a wrong function?
If your pins array is as simple as that, you don't need anything just vanilla JavaScript.
new Vue({
el: "#app",
data: {
pins: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
pin: '',
result: ''
},
methods: {
isThisPin() {
if (this.pin) {
this.result = this.pins.includes(Number(this.pin))
} else {
this.result = ''
}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<label>IS THIS PIN: <input type="number" v-model="pin" #input="isThisPin"></label>
<br /> RESULT: {{result}}
</div>
This can be achieved with plain javascript:
var fruits = ["Banana", "Orange", "Apple", "Mango"]
var a = fruits.indexOf("Apple")
Returns index of the item or -1 if not found
or
var fruits = ["Banana", "Orange", "Apple", "Mango"];
var n = fruits.includes("Mango");
Returns true or false
If you want to use lodash you use _.contains also the snippet works with lodash
_.contains([1, 2, 3], 'X') // false
var pins = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
//alert(_.includes(pins, 'X'));
function checkPin(pin){
return _.includes(pins,pin )
}
alert(checkPin('X'));
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.15/lodash.min.js"></script>
You can use Array.prototype.findIndex() as below
var pins = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
console.log( pins.findIndex(e => e == 'x') != -1 );
console.log( pins.findIndex(e => e == 9) != -1 );
The thing is, your snippet does work and _.includes does work - run snippet to check. Therefore the problem must be somewhere else.
const pins = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
function isThisPin(pin) {
return _.includes(this.pins, pin);
}
console.log(this.isThisPin('X'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>

Categories