What does these ES6 syntaxes really change? - javascript

Trying to learn some functional javascript and es6 concepts.
I have an array
var _ = require('underscore');
var raw =[
{
key :"name",value:"henry"
},
{
key :"age",value:"old"
},
{
key :"food",value:"matooke"
},
{
key :"kids",value:"Acacia"
},
{
key :"garbageA",value:"kasailoA"
},
{
key :"garbageB",value:"kasasiroB"
},
]
I am trying to filter out data with garbage keys . I have two codes that return different results and I wonder why they do not return the same results.
When i write
const endShape = _(raw)
.filter(key =>!/garbage/.test(key));
console.log(endShape);
in my console it prints.
[ { key: 'name', value: 'henry' },
{ key: 'age', value: 'old' },
{ key: 'food', value: 'matooke' },
{ key: 'kids', value: 'Acacia' },
{ key: 'garbageA', value: 'kasailoA' },
{ key: 'garbageB', value: 'kasasiroB' } ]
showing that my filter dint work.
When i write
const endShape = _(raw)
.filter({key} =>!/garbage/.test(key));
console.log(endShape);
It brings a syntax error.
But when i write
const endShape = _(raw)
.filter(({key}) =>!/garbage/.test(key));
console.log(endShape);
my filter works well and it prints
[ { key: 'name', value: 'henry' },
{ key: 'age', value: 'old' },
{ key: 'food', value: 'matooke' },
{ key: 'kids', value: 'Acacia' } ]
Why is it this way ? yet i know from phat arrow syntax that its okay to write
var x = y=>y+1;
and also
var x =(y)=>y+1

Actually the first and the second key for your filter is quite different.
On the first run when you do:
const endShape = _(raw)
.filter(key =>!/garbage/.test(key));
You are passing an object from your raw array, and your check is being evaluated like:
!/garbage/.test({ key: 'name', value: 'henry' })
Which will always be evaluated to false, and then you negate it so every condition will be true, thus your filter let every entry pass.
On the second run you do:
const endShape = _(raw)
.filter(({key}) =>!/garbage/.test(key));
Where you're destructuring key from your object, and thus the test makes sense, and your filter works fine!
Hope it helps!

Related

Return all values of nested arrays using string identifier

Given an object searchable, is there a simple way of returning all the id values using lodash or underscore.js (or equivalent) where I can define the path to id?
const searchable = {
things: [
{
id: 'thing-id-one',
properties: [
{ id: 'd1-i1' },
{ id: 'd1-i2' },
]
},
{
id: 'thing-id-two',
properties: [
{ id: 'd2-i1' },
{ id: 'd2-i2' },
]
}
]
}
I am looking to see if this is possible in a manner similar to how we can use lodash.get e.g. if we wanted to return the things array from searchable we could do
const things = _.get(searchable, 'things');
I can't seem to find anything similar in the documentation. I am looking for something
that could contain an implementation similar to:
_.<some_function>(searchable, 'things[].properties[].id')
Note: I am well aware of functions like Array.map etc and there are numerous ways of extracting the id property - it is this specific use case that I am trying to figure out, what library could support passing a path as a string like above or does lodash/underscore support such a method.
Found a solution using the package jsonpath
const jp = require('jsonpath');
const result = jp.query(searchable, '$.things[*].properties[*].id')
console.log(result);
// outputs: [ 'd1-i1', 'd1-i2', 'd2-i1', 'd2-i2' ]
you can do it easily in plain js
like this
const searchable = {
things: [
{
id: 'thing-id-one',
properties: [
{ id: 'd1-i1' },
{ id: 'd1-i2' },
]
},
{
id: 'thing-id-two',
properties: [
{ id: 'd2-i1' },
{ id: 'd2-i2' },
]
}
]
}
const search = (data, k) => {
if(typeof data !== 'object'){
return []
}
return Object.entries(data).flatMap(([key, value]) => key === k ? [value]: search(value, k))
}
console.log(search(searchable, 'id'))
_.map and _.flatten together with iteratee shorthands let you expand nested properties. Every time you need to expand into an array, just chain another map and flatten:
const searchable = {
things: [
{
id: 'thing-id-one',
properties: [
{ id: 'd1-i1' },
{ id: 'd1-i2' },
]
},
{
id: 'thing-id-two',
properties: [
{ id: 'd2-i1' },
{ id: 'd2-i2' },
]
}
]
}
// Let's say the path is "things[].properties[].id"
const result = _.chain(searchable)
.get('things').map('properties').flatten()
.map('id').value();
console.log(result);
<script src="https://cdn.jsdelivr.net/npm/underscore#1.13.4/underscore-umd-min.js"></script>

How can I extract and pair the values of an array based object

I'm trying to create a String based upon an object consisting of several key-value pairs.
Example:
[{ name: 'cookie1', value: 'false' },
{ name: 'cookie2', value: '123' },
{ name: 'cookie3',value: 'abc'}]
What I'm trying to achieve (string):
cookie1: false, cookie2: 123, cookie3: abc
I've tried to extract just the val using map like this (played around moving around values):
var output = cookies.map(d => {
return {
"name": d.name,
"value": d.value,
}
})
One way to do this is to map the array of objects into name: value strings and then join them with , :
const data = [{ name: 'cookie1', value: 'false' },
{ name: 'cookie2', value: '123' },
{ name: 'cookie3',value: 'abc'}]
const result = data.map(({ name, value }) => `${name}: ${value}`).join(', ')
console.log(result)

react adding new array method to return array's object item by it's key

I have some enum objects and i want to get its lebel by it's value.
Let's say this is my enum list
const enumList = {
businessType: [
{ value: "b", label: "B2B" },
{ value: "s", label: "SAAS" },
{ value: "c", label: "C2C" },
],
userType: [
{ value: "A", label: "Admin" },
{ value: "s", label: "Super User" },
{ value: "t", label: "trainer" },
]
}
So now I want to get a particular object label by its key.
like this,
enumList.userType.getLabel('s')'
// super user
I mean, i want to make it re-usable, currently i am doing like this and i dont like it
index = enumList.userType.findIndex(x => x.value ==="s");
enumList.userType[index].label
// super user
Does anyone know how can i make it re-usable to access it from globally like this enumList.userType.getLabel('s) ?
This custom Array method will allow you to do this enumList.userType.getLabel('s') and receive 'Super User'
Array.prototype.getLabel = function(val) {
return this.find(({value}) => value === val).label
}
See Why is extending native objects a bad practice?
It looks like you want a one-liner, so just use find
const { label } = enumList.userType.find(userType => userType.value === 's');

How do I populate an array of objects where every object has an array inside of it using response from rest API?

I can't google the right solution for this for about an hour straight,
So I'm getting a response from the API that looks like this:
[
{
"Name": "name1",
"Title": "Name One",
"Children": [
{
"Name": "Name 1.1",
"Title": "Name one point one"
},
]
And I need it to fit this kind of "mold" for the data to fit in:
{
title: 'Name One',
value: 'name1',
key: '1',
children: [
{
title: 'Name one point one',
value: 'Name 1.1',
key: 'key1',
},
I am trying to achieve this using a foreach but It's not working as intended because I need to do this all in one instance of a foreach.
Here's what I gave a go to(vue2):
created() {
getData().then(response => {
const formattedResponse = []
response.forEach((el, key) => {
formattedResponse.title = response.Title
formattedResponse.name = response.Name
formattedResponse.children = response.Children
})
})
Use map over the main array and use destructuring assignment to extract the properties by key, and relabel them, and then do exactly the same with the children array. Then return the updated array of objects.
const data=[{Name:"name1",Title:"Name One",Children:[{Name:"Name 1.1",Title:"Name one point one"}]},{Name:"name2",Title:"Name Two",Children:[{Name:"Name 1.2",Title:"Name one point two"}]}];
const result = data.map((obj, key) => {
const { Title: title, Name: value } = obj;
const children = obj.Children.map(obj => {
const { Title: title, Name: value } = obj;
return { title, value, key: (key + 1).toString() };
});
return { title, value, children };
});
console.log(result);
Your API response is JSON. All you need to do is:
var resp=JSON.parse(API response);

Convert flat json structure to hierarchical

I cannot get my head around this problem.
I have a settings object which looks like
const setting = [
{
Key: 'root/',
Value: null,
},
{
Key: 'root/second-root/',
Value: null,
},
{
Key: 'root/second-root/names/',
Value: null,
},
{
Key: 'root/second-root/names/capital-letter',
Value: true,
},
{
Key: 'root/second-root/countries/',
Value: null,
},
{
Key: 'root/second-root/countries/enabledcountries',
Value: 'US,UK,DK',
},
{
Key: 'root/second-root/countries/async',
Value: 'true',
},
{
Key: 'root/second-root/countries/manual',
Value: 'true',
},
{
Key: 'root/second-root/countries/limit',
Value: '4200',
},
{
Key: 'root/second-root/names/onyl-last-name',
Value: false,
},
];
I need to convert it to look like
const wantedResult = [
{
'root': {
'Value': null,
'second-root': {
'Value': null,
'names': {
'Value': null,
'capital-letter': {
'Value': true,
}
'onyl-last-name': {
'Value': false,
}
},
'countries': {
'Value': null,
'enabledcountries': {
Value: 'US,UK,DK',
},
'async': {
Value: 'true',
},
'manual': {
Value: 'true',
},
'limit': {
Value: '4200',
}
}
}
}
}
];
The it is the Key property which controls the hierarchy. If it ends with a / the item is a directory else it is a value.
Problem is that the flat structure doesnt have to return the items in a correct order. Like in the example, the last item is 'root/second-root/names/onyl-last-name', even though the names hiarchy was in the beginning of the flat structure.
I have tried a form of array.reduce but get stuck every time. Could someone please help me.
You could iterate the array and take the value without the last slash and split it as path to the object for assigning the value.
If necessary put the result in an array.
In forEach works
a destructuring assignment for getting the key and value out of the object,
a replacement which looks for a slash at the end of the string with an empty string,
a splitting of the string by slash, it returns an array with strings without slashes,
using Array#reduce with the result object as accumulator.
Inside it uses a default pattern with a logical OR || which check if the left side is a truthy value and if not, it assigns an object. This value is returned for the check with the next key.
at the end of the iteration it retuns an object reference and then the value gets assigned.
var setting = [{ Key: 'root/', Value: null }, { Key: 'root/second-root/', Value: null }, { Key: 'root/second-root/names/', Value: null }, { Key: 'root/second-root/names/capital-letter', Value: true }, { Key: 'root/second-root/countries/', Value: null }, { Key: 'root/second-root/countries/enabledcountries', Value: 'US,UK,DK' }, { Key: 'root/second-root/countries/async', Value: 'true' }, { Key: 'root/second-root/countries/manual', Value: 'true' }, { Key: 'root/second-root/countries/limit', Value: '4200' }, { Key: 'root/second-root/names/onyl-last-name', Value: false }],
result = {};
setting.forEach(({ Key, Value }) => Key
.replace(/\/$/, '')
.split('/')
.reduce((o, k) => o[k] = o[k] || {}, result).Value = Value
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Categories

Resources