Getting multi-dimensional array value using Javascript / node.js - javascript

I have an Object that looks like this>
let arr = [
['animal','lion'],
['plant','rose'],
['tree','coconut'],
]
I want to make my code look like this:
['animal','lion']
['plant','rose']
['tree','coconut']
For this, I tried this method:
let sep1=arr[0];
let sep2=arr[1];
Getting value as:
['animal','lion']
['plant','rose']
I have to repeat the code 3 time to get the output, but what if there is 30 arrays inside an object? Any solution?
Ps: I am weak in coding bear with me :slight_smile:

If you want to be able to access the separate arrays by key, you could map() through your array and create entries to create an object from. That way, you could access a specific array by property key.
let arr = [
['animal', 'lion'],
['plant', 'rose'],
['tree', 'coconut'],
];
const result = Object.fromEntries(arr.map((a, i) => {
return [`sep${i}`, a]; // return ['sepX', [x, x]] as entries
}));
console.log("result", result);
console.log("sep0", result.sep0);
console.log("sep1", result.sep1);
console.log("sep2", result.sep2);

Related

How to sort the nested object data in react-native

{
"lion":{
"age_in_years":"10",
"name":"king",
"country":"africa"
},
"elephant":{
"age_in_years":"15",
"name":"hero",
"country":"usa"
},
"racoon":{
"age_in_years":"5",
"name":"thanos",
"country":"syria"
},
}
This is the data I'm getting through a web socket in react-native. I want to sort it in ascending order based on the "age_in_years". So the oldest animal's data should be shown at top and the youngest data at the last.
You sould better work with an array insted of object as below, first map it into array and parse the age_in_years and sort it.
const obj2Array = Object.entries(<YourObject>).map(([key, value]) => ({...value, _id: key, age_in_years: parseInt(value.age_in_years)}));
const sorted = obj2Array.sort((a, b) => a.age_in_years - b.age_in_years);
Then you can use .reduce if you want the object back, nevertheless you can use the sorted array to render it.
Sort by age in years oldest first
// use slice() to copy the array
var byAge = array.slice(0);
byAge.sort(function(a,b) {
return a.age_in_years - b.age_in_years ;
});
Store the values in array and make a sort function.
const numbers = [info.lion.age_in_years, info.elephant.age_in_years, info.racoon.age_in_years];
const ascNumbers = numbers.sort((a,b) => a-b);
If you need descending make it like this:
const descNumbers = numbers.sort((a,b) => b-a);

Filtering an object array with another array

I am having a filtering problem..
objArray is the array that needs to be filtered.
selectedNames is an array that contains the values that I want to find in objArray.
I need to fetch all objects that have one or more values from selectedNames in their "names" property (an array) .
The output I am trying to get is :
let result = [{names:["A","B","C","D"]},
{names:["A","B"]},
{names:["A","D"]}
]
Here is a simplified version of my code:
let objArray = [{names:["A","B","C","D"]},
{names:["C","D"]},
{names:["C","D","E"]},
{names:["A","B"]},
{names:["A","D"]}
]
let selectedNames = ["A","B"]
result = this.objArray .filter(obj => {
return this.selectedNames.includes(obj.names)
}
My code seems to work fine if names attribute was a single value and not an array. But I can't figure out how to make it work on an array.
Any help is more than welcome
You could do something like this. Filtering the array based on the names property having 'some' value be included in the selectedNames array.
...
objArray.filter(obj => obj.names.some(name => selectedNames.includes(name)));
[Edit] As #RadicalTurnip pointed out, this is not performant if the selectedNames is too large. I would suggest that you use an object. E.x
...
const selectedNamesMap = selectedNames.reduce((p,c) => ({...p, [c]: true}), {});
objArray.filter(obj => obj.names.some(name => selelectedNamesMap[name]));
Overkill, but if the arrays are really large (millions of elements) then you are better of using regular for loop and not array methods.
This result is not performant scaled up, but I don't know that there is any way to ensure that it will be performant unless you know more information (like the names are already sorted). That being said, you just missed one more piece of logic.
result = this.objArray.filter(obj => {
let toReturn = false;
obj.names.forEach(name => {
if (this.selectedNames.includes(name))
toReturn = true;
};
};
return toReturn;
};

How to modify an array of array, depending if an element in it matches an element from another array of array?

I have 2 set of array of arrays in Google Spreadsheet as follows:-
var arrayInput = [[ASIAPLY, "9/10/2020"], [PCCS, "9/10/2020"], [SCGM, "9/10/2020"]]
var arrayOuput = [[PCCS, "8/10/2020"]]
I want to insert the 2nd index of an element/array in the arrayInput if the 1st index is present in the outputArray. If it is not, I would like to add the whole element/array into outputArray. My desired outcome would look like this
var arrayOuput = [[PCCS, "9/10/2020", "8/10/2020"], [ASIAPLY, "9/10/2020"], [SCGM, "9/10/2020"]]
I have tried this
function testData() {
// get the range of input data
var arrayInput = wlSheet.getRange(2, 2, 3, 2).getValues();
// get the range of output counter
var arrayOuput = wlSheet.getRange(2, 7, 1, 2).getValues();
arrayOuput.find((outputRow, i, arr) => {
arrayInput.map((r, index, array) => {
if (r[0] !== outputRow[0]) {
return wlSheet.getRange(arr.length + 2 + index, 7, 1, 2).setValues([[counter, hyperlinkText]]);
} else {
return wlSheet.getRange(i + 2, 8).insertCells(SpreadsheetApp.Dimension.COLUMNS).setValue(hyperlinkText);
}
});
});
}
However the code above has resulted into [[PCCS, "9/10/2020", "8/10/2020"], [PCCS, "9/10/2020"], [ASIAPLY, "9/10/2020"], [SCGM, "9/10/2020"]]; instead of desired result.
Is there a way of achieving what I intended to do in Google Apps Script?
Thanks in advance.
If you want to insert an item, you can't use Array.prototype.map as it will return a new array.
Now i'm not familiar with google apps scripts, or interacting with spreadsheets, but the basic JS would look like this:
What you are trying can be easily done with a for...of-loop
The basic steps are:
we have two arrays in the shape of a key followed by a number of values
if your familiar with TypeScript types: [key: Key, ...values: string[]]
we want to take from input to output
for each element in input
if output has an element with the corresponding key: append own values to it
else add self to output
const inArr = [['ASIAPLY', '9/10/2020'], ['PCCS', '9/10/2020'], ['SCGM', '9/10/2020']]
const outArr = [['PCCS', '8/10/2020']]
// iterate over the array elements and use destructuring to
// extract the key form the other values
for (const [key, ...values] of arrayInput) {
// look for an element in `output` that has that key
const target = outArr.find(([ky, value]) => ky === key)
// if we found one, push the values to it
if (target) target.push(...values)
// else push your key-values onto the output array
else outArr.push([key, ...values])
}
The result using the example arrays is:
[
[ 'PCCS', '8/10/2020', '9/10/2020' ],
[ 'ASIAPLY', '9/10/2020' ],
[ 'SCGM', '9/10/2020' ]
]
Since we used spread syntax (...values) in the destructuring, this is little iterator is able to handel 0 or more values by default and will always output the approptiate result.
This should solve this problem in an elegant manner and it is easyly modifiable if needed.
Create a new output array using Map and Array.map:
/*<ignore>*/console.config({maximize:true,timeStamps:false,autoScroll:false});/*</ignore>*/
const array1 = [
['ASIAPLY', '9/10/2020'],
['PCCS', '9/10/2020'],
['SCGM', '9/10/2020'],
],
array2 = [['PCCS', '8/10/2020']],
array2Map = new Map(array2),
arrayOutput = array1.map(([k, v]) => [k, v, array2Map.get(k)]);
console.log(arrayOutput);
<!-- https://meta.stackoverflow.com/a/375985/ --> <script src="https://gh-canon.github.io/stack-snippet-console/console.min.js"></script>
To use setValues, the arrays must be of uniform size.

Javascript - Workaround for flatmap

So I was looking for some workaround for flat map as it doesn't work on IE and I find this one:
But I don't really understand why does it work
var gadjets = [
{computers:['asus', 'hp'],
sellphones:['Galaxy', 'Nokia']
},
{computers:['dell', 'insys'],
sellphones:['iphone', 'samsung']
}
];
const getValues = gadjets.reduce((acc, gadjet) => acc.concat(gadjet[computers]), []) // instead of gadjets.flatMap(gadjet=> gadjet[computers])
This code returns:
['asus','hp','dell','insys']
But shouldn't it return:
['asus','hp'],['dell', 'insys']
This is because reduce adds up the elements you give it. For example, take the following code:
let arr = [1,2,3,4,5];
console.log(arr.reduce((before, value)=>before+value));
This code takes each value and adds it to before. It then passes that added value into the next iteration of reduce, in the before variable.
In your code, you were passing an array into before, or in your case acc, and concatenates (merge) a new array from gadgets['computers'] and returns that array. This creates a list of the computers from the array of objects.
More info on reduce here.
But shouldn't it return
I'm not sure what you're trying to show us there, but if you mean
[['asus','hp'],['dell', 'insys']]
then no, it shouldn't. concat flattens arrays you pass it (to a single level):
const a = [].concat(['asus','hp'], ['dell', 'insys']);
console.log(a); // ["asus", "hp", "dell", "insys"]
So acc.concat(gadjet[computers]) flattens out each of those computers arrays into a new array, which is the accumulation result of the reduce.
In case you want the output to be array of arrays. Try this:
var gadjets = [
{ computers: ["asus", "hp"], sellphones: ["Galaxy", "Nokia"] },
{ computers: ["dell", "insys"], sellphones: ["iphone", "samsung"] }
];
const groupBy = key => {
let res = gadjets.reduce((objectsByKeyValue, obj) => {
let arr = [];
arr.push(obj[key]);
return objectsByKeyValue.concat(arr);
}, []);
return res;
};
console.log(groupBy("computers"));

turning an array into an array with objects

I have been trying to figure out how to turn an array into an array with objects.
for example i have a json file to start with and the json file looks sorta like this
var data=[{"tasknumber":304030,
"date":"2012-05-05",
"operator":"john doe"},
{"tasknumber":23130,
"date":"2012-07-07",
"operator":"john doeeeeeeee"},
{"tasknumber":233330,
"date":"2012-08-08",
"operator":"john doe"}]
so i applied the _.countBy function that is within the underscore.js library and i get an object like this
{"john doe":2,"john doeeeeeeee":1}
ive been trying to figure out how to turn this into an array with objects so it would look something like this but i have failed in every attempt and i dont know were to start
[{operator:"john doe",
count: 2},
{operator: "john doeeeeeeee",
count:1}]
i have tried a few things but all i get is tragedy and everything breaks, does anyone know if there are any librarys or anything that could help with this sort of thing?
Given the object (not array) {"john doe":2,"john doeeeeeeee":1} as input you can get your desired output like this:
var input = {"john doe":2,"john doeeeeeeee":1};
var output = Object.keys(input).map(function(k) {
return {
operator: k,
count: input[k]
};
});
console.log(output);
Or with ES6 arrow function syntax:
var input = {"john doe":2,"john doeeeeeeee":1};
var output = Object.keys(input).map((k) => ({ operator: k, count: input[k] }) );
console.log(output);
(Note that Underscore probably provides an even shorter way to do this, but I'm not familiar with Underscore so I've just given a plain JS solution.)
Further reading:
Object.keys()
array .map()
=> arrow functions
Given your initial data array, you can just run this:
var data=[{"tasknumber":304030,
"date":"2012-05-05",
"operator":"john doe"},
{"tasknumber":23130,
"date":"2012-07-07",
"operator":"john doeeeeeeee"},
{"tasknumber":233330,
"date":"2012-08-08",
"operator":"john doe"}];
Function definition
const count = data => {
// get data in format like _.countBy
const o = data.map(x => x.operator).reduce((acc, cur) => { acc[cur] ? acc[cur] += 1 : acc[cur] = 1; return acc; }, {});
// transform object into array of object
return Object.keys(o).map(operator => ({operator, count: o[operator]}));
};
Test it by producing output
console.log(count(data));
Here is an untested underscore approach that takes your initial values as loaded from the JSON file and converts directly into your desired output format:
_.chain(input)
.groupBy(function(entry) { return entry.operator })
.map(function(entries, operator) {
return {
operator: operator,
count: entries.length
}
})
.value();

Categories