ES6 implementation of this function? - javascript

This function loops through an array of objects, and takes an object as a second parameter.
It will loop through the array of objects replacing it with the object passed in as the second argument if the firstname value matches.
I am sure there is a better way of implementing this function using ES6 spread operator but I'm having trouble implementing it.
const foo = (arr, obj) => {
const tempArray = arr.map((item, i) => {
if ( arr[i].name === obj.name ) {
return obj
} else {
return arr[i]
}
})
return tempArray
}
const arrOfObjx = [
{
"name": "Joe",
"favMovie": "Rambo"
},
{
"name": "Jane",
"favMovie": "The Matrix"
},
{
"name": "John",
"favMovie": "Star Wars"
}
]
const newJoe = {
"name": "Joe",
"favMovie": "ROCKY"
}
console.log(foo(arrOfObjx, newJoe ))

No, there is no use case for the spread operator here. The simplifications to make are in dropping the tempArray variable and in using item instead of arr[i]:
function foo(arr, obj) {
return arr.map((item, i) => {
if ( item.name === obj.name ) {
return obj
} else {
return item
}
});
}
which you can further shorten to
const foo = (arr, obj) =>
arr.map(item =>
item.name === obj.name ? obj : item
);

Try out using item
const tempArray = arr.map((item, i) => {
if (item.name === obj.name) {
return obj
} else {
return item
}
})
I think you can even write it as
const tempArray = arr.map((item, i) => {
return (item.name === obj.name ? obj : item)
})

Related

How to get values from array of objects in javascript

I have an array of object from which I am trying to get values using map operator but I am getting the whole json objects all I want is just array of values.
Below is my code:
const obj = [
{
a: {
b: 'Paul',
}
},
{
c: 'Byeeee',
}
];
obj.map((val) => console.log(val));
what I am getting is
{ a: { b: 'Paul' } }
{ c: 'Byeeee' }
What I want is:
['Paul','Byeeee']
Someone let me know how can I get the desired output.
You can do this recursively. You can first start off by grabbing the values of your object, and then loop through those using .flatMap(). If you encounter a value that is an object, you can recursively grab the values of that object by recalling your function. Otherwise, you can return the value. The advantage of using .flatMap() here is that when the recursive call returns an array, we don't end up with inner arrays, but rather the array gets flattened into one resulting array:
const obj = [{ a: { b: 'Paul', } }, { c: 'Byeeee', } ];
const getValues = (obj) => {
return Object.values(obj).flatMap(val => Object(val) === val ? getValues(val) : val);
}
console.log(getValues(obj));
you can use the following solution.
const data = [{ a: { b: 'Paul' } }, { c: 'Byeeee' }];
const flatObjectValues = (obj, result) => {
// recursive function to get object values
const objValues = Object.values(obj);
if (objValues?.length > 0) {
objValues.map((v) => {
if (typeof v === 'object' && !Array.isArray(v)) {
flatObjectValues(v, result);
} else {
result.push(v);
}
return v;
});
}
};
const updatedData = [];
data.map((x) => flatObjectValues(x, updatedData));
console.log('updatedData: ', updatedData);
You can use recursion with array.reduce, like fellowing.
function getAllValues(objuct) {
return objuct.reduce((acc, curr) => {
if (typeof curr === 'object') {
return [...acc, ...getAllValues(Object.values(curr))];
}
return [...acc, curr];
}, []);
}
A recursive solution could be:
const arr = [{a: {b: "Paul",},},{c: "Byeeee",},];
const flatArrOfObjects = (arr) => {
const values = [];
for (const i in arr) flatObj(arr[i], values);
return values;
};
const flatObj = (obj, result) => {
for (const [key, value] of Object.entries(obj)) {
if (typeof value === "object") flatObj(value, result);
else result.push(value);
}
};
console.log(flatArrOfObjects(arr));

JavaScript Filter Loop Not Looping Through All Item In Array

In the following code I am trying to filter the data. However, I see in the algorithm that it loops through the first item in the userPassedFilter array and returns the filtered data but doesn't loop again to check the second item in the userPassedFilter array. I know this is happening because I call return true before it iterates through the entire userPassedFilter array. How can I assure that in the algorythm that it loops through all the items in the userPassedFilter before returning the final result?
**User Selected Filter**
let userPassedFilter = [{"phase":1},{"phase":2}]
**Data**
let dataList = [
{"voltage":35, "phase":2},
{"voltage":12, "phase":2},
{"voltage":12, "phase":3},
{"voltage":35, "phase":1}
]
**Filter Data Algorithm**
module.exports = {
filterData: (dataList, userPassedFilter)=>{
let filteredData = [];
filteredData = dataList.filter((data) =>{
for(let item of userPassedFilter){
for(let key in item){
if(data[key] === undefined || data[key] !== item[key])
return false
}
}
return true
})
return filteredData
}
}
filter over the dataList and return every object where some of its object properties are included in the userFilter.
const userPassedFilter = [{voltage:122},{phase:1},{phase:2},{voltage:44}];
const dataList = [
{voltage:44, phase:12},
{voltage:35, phase:2},
{voltage:12, phase:2},
{voltage:12, phase:3},
{voltage:35, phase:1},
{voltage:122, phase:156}
];
function filterData(dataList, userPassedFilter) {
return dataList.filter(obj => {
return userPassedFilter.some(inner => {
const [[ key, value ]] = Object.entries(inner);
return obj[key] === value;
});
});
}
console.log(filterData(dataList, userPassedFilter));
Introduce variable for each loop, so the result will match any of the elements in the userPassedFilter by matching all properties for the element.
let userPassedFilter = [{"phase":1},{"phase":2}];
let dataList = [{"voltage":35, "phase":2},{"voltage":12, "phase":2},{"voltage":12, "phase":3},{"voltage":35, "phase":1}];
const f = (dataList, userPassedFilter) => {
let filteredData = dataList.filter((data) => {
let filtered = true;
for (let item of userPassedFilter) {
let matched = true;
for (let key in item) {
if (data[key] === undefined || data[key] !== item[key]) {
matched = false;
break;
}
}
if (matched) {
filtered = false;
break;
}
}
return !filtered;
});
return filteredData;
};
console.log(f(dataList, userPassedFilter));
A shorter version:
let userPassedFilter = [{"phase":1},{"phase":2}];
let dataList = [{"voltage":35, "phase":2},{"voltage":12, "phase":2},{"voltage":12, "phase":3},{"voltage":35, "phase":1}];
const f = (dataList, userPassedFilter) => {
let filteredData = dataList.filter((data) => {
return userPassedFilter.some(item => Object.entries(item).every(([key, value]) => data[key] === value))
});
return filteredData;
};
console.log(f(dataList, userPassedFilter));
try adding a variable
filteredData = dataList.filter((data) => {
let myvar = true;
for(let item of userPassedFilter){
for(let key in item){
if(data[key] === undefined || data[key] !== item[key])
myvar = false
}
}
return myvar
})
try adding a variable to hold the values:
let userPassedFilter = [{
"phase": 1
}, {
"phase": 2
}]
let dataList = [{
"voltage": 35,
"phase": 2
},
{
"voltage": 12,
"phase": 2
},
{
"voltage": 12,
"phase": 3
},
{
"voltage": 35,
"phase": 1
}
]
function filterData(dataList, userPassedFilter) {
let filteredData = [];
filteredData = dataList.filter((data) => {
var throwVar = 0 //add this variable to hold the value
for (let item of userPassedFilter) {
for (let key in item) {
if (data[key] === undefined || data[key] !== item[key]) {
throwVar = 0
} else {
return true
}
}
}
if (throwVar == 0) {
return false
}
})
return filteredData
}
console.log(filterData(dataList, userPassedFilter))

Javascript: recursively encode and decode querystring. (object to querystring, querystring to object)

I want to encode a complex json/javascript object into the standard querystring encoding.
And i want to decode this querystring back to an json/javascript object.
It should be recursively, with arrays, objects, strings, booleans and numbers.
I thought this should be easy, but was proven wrong. Does anyone have an idea, how to solve this problem?
Either in Javascript or preferably in Typescript.
I think, what you want to do, is encode and decode nested objects.
There is no single standard, but very often, QS (Query String) syntax is used:
{
"attribute": "value",
"array": ["apples", "bananas"],
"object": { "number": 55 },
}
will become:
?attribute=value&array[0]=apples&array[1]=bananas&object[number]=55
Example code:
function decode(querystring: string): object {
function parseValue(value: string): any {
if (value === 'TRUE') return true;
if (value === 'FALSE') return false;
return isNaN(Number(value)) ? value : Number(value);
}
function dec(list: any[], isArray = false): object {
let obj: any = isArray ? [] : {};
let recs: any[] = list.filter((item) => {
if (item.keys.length > 1) return true;
obj[item.keys[0]] = parseValue(item.value);
});
let attrs = {};
recs.map((item) => {
item.key = item.keys.shift();
attrs[item.key] = [];
return item;
}).forEach((item) => attrs[item.key].push(item));
Object.keys(attrs).forEach((attr) => {
let nextKey = attrs[attr][0].keys[0];
obj[attr] = dec(attrs[attr], typeof nextKey === 'number');
});
return obj;
}
return dec(
querystring
.split('&')
.map((item) => item.split('=').map((x) => decodeURIComponent(x)))
.map((item) => {
return {
keys: item[0]
.split(/[\[\]]/g)
.filter((n) => n)
.map((key) => (isNaN(Number(key)) ? key : Number(key))),
value: item[1],
};
})
);
}
export function encode(object: object): string {
function reducer(obj, parentPrefix = null) {
return function (prev, key) {
const val = obj[key];
key = encodeURIComponent(key);
const prefix = parentPrefix ? `${parentPrefix}[${key}]` : key;
if (val == null || typeof val === 'function') {
prev.push(`${prefix}=`);
return prev;
}
if (typeof val === 'boolean') {
prev.push(`${prefix}=${val.toString().toUpperCase()}`);
return prev;
}
if (['number', 'string'].includes(typeof val)) {
prev.push(`${prefix}=${encodeURIComponent(val)}`);
return prev;
}
prev.push(
Object.keys(val).reduce(reducer(val, prefix), []).join('&')
);
return prev;
};
}
return Object.keys(object).reduce(reducer(object), []).join('&');
}
const obj = { key: 1, key1: 2, key2: 3 }
const params = encodeURIComponent(JSON.stringify(obj))
window.location.href = `http://example.com/?query=${params}`
end like this:
http://example.com/?query=%7B%22key%22%3A1%2C%22key1%22%3A2%2C%22key2%22%3A3%7D

how to convert api respons ekey value in camelcase

I am getting some api response , where I have to change all key value is camelcase ..
like below I am getting response . i have to convert all key is small .
like CBSServiceResponseDtls = cBSServiceResponseDtls same for all keys .
Dont want to change any of value And few of keys has _ .
Like "API_OUTPUT" I have to change in apiOutput.
Please help. Thanks
{
"CBSServiceResponseDtls":{
"Response":{
"ResultStatus":{
"ResultCode":0,
"ResultMessage":"SUCCESS"
},
"Data":{
"EVENT":{
"API_OUTPUT":{
"SUCCESS_FLAG":0,
"REQUEST_STATUS":0,
"ABILLITY_REF_NUM":32038,
"RESPONSE_ERROR_CODE":"",
"SUCCESS_MESG_LANG_1":"Request has been Processed Successfully",
"SUCCESS_MESG_LANG_2":"Request has been Processed Successfully",
"TRANSACTION_LOG_REFERNCE":2.0200507064507202e+27
},
"LOGIN_DETAILS":{
"LOGIN_DTLS":[
{
"LOGIN_NAME":"soban",
"LOCATION_CODE":"WAREHOUSE",
"LOCATION_CODE_NO":1,
"LOCATION_DESC":"WAREHOUSE",
"DEFAULT_FLAG":"Y"
},
{
"LOGIN_NAME":"soban",
"LOCATION_CODE":"BTP",
"LOCATION_CODE_NO":70,
"LOCATION_DESC":"BTP",
"DEFAULT_FLAG":"N"
}
]
}
}
}
}
}
}
Simple solution, You can use regex replace/transform function to change all keys.
More: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
CamelCase Sample:
const toCamelCase = (str = "") => {
const [first, ...rest] = str.split("_");
return (
first.toLowerCase() +
rest
.map((word) => {
word = word.toLowerCase();
return word.slice(0, 1).toUpperCase() + word.slice(1);
})
.join("")
);
};
const tranform = (m) =>
m.indexOf("_") === -1
? m.slice(0, 1).toLowerCase() + m.slice(1)
: toCamelCase(m);
const formatJson = (obj) => {
const jsonString = JSON.stringify(obj).replace(
/\"(\w+)\":/g,
(_, m) => `"${tranform(m)}":`
);
return JSON.parse(jsonString);
};
const data = {"CBSServiceResponseDtls":{"Response":{"ResultStatus":{"ResultCode":0,"ResultMessage":"SUCCESS"},"Data":{"EVENT":{"API_OUTPUT":{"SUCCESS_FLAG":0,"REQUEST_STATUS":0,"ABILLITY_REF_NUM":32038,"RESPONSE_ERROR_CODE":"","SUCCESS_MESG_LANG_1":"Request has been Processed Successfully","SUCCESS_MESG_LANG_2":"Request has been Processed Successfully","TRANSACTION_LOG_REFERNCE":2.0200507064507202e+27},"LOGIN_DETAILS":{"LOGIN_DTLS":[{"LOGIN_NAME":"soban","LOCATION_CODE":"WAREHOUSE","LOCATION_CODE_NO":1,"LOCATION_DESC":"WAREHOUSE","DEFAULT_FLAG":"Y"},{"LOGIN_NAME":"soban","LOCATION_CODE":"BTP","LOCATION_CODE_NO":70,"LOCATION_DESC":"BTP","DEFAULT_FLAG":"N"}]}}}}}}
const json = formatJson(data);
console.log("%j", json);
You can use this helper function to do it recursively:
function objToLowerCase(obj) {
if (Array.isArray(obj)) {
return obj.map((entry) => typeof entry !== "object" ? entry : objToLowerCase(entry));
}
const newObj = Object.entries(obj).reduce((obj, [key, value]) => {
const newKey = key.toLowerCase().split("_").join("");
const newValue = typeof value !== "object" ? value : objToLowerCase(value);
obj[newKey] = newValue;
return obj;
}, {});
return newObj;
}
Here is a sandbox.
To make it camelCase, you could use this function:
function toCamelCase(str) {
if (str === str.toUpperCase()) {
return str
.toLowerCase()
.split("_")
.map((s, i) =>
i === 0 ? s : s.slice(0, 1).toUpperCase() + s.slice(1, s.length)
)
.join("");
} else {
return str.slice(0, 1).toLowerCase() + str.slice(1);
}
}
and call it like this:
function objToLowerCase(obj) {
if (Array.isArray(obj)) {
return obj.map((entry) => typeof entry !== "object" ? entry : objToLowerCase(entry));
}
const newObj = Object.entries(obj).reduce((obj, [key, value]) => {
const newKey = toCamelCase(key)
const newValue = typeof value !== "object" ? value : objToLowerCase(value);
obj[newKey] = newValue;
return obj;
}, {});
return newObj;
}

ES6 filter in a filter is this possible?

I have an Array that looks like this:
I need the id where slug === 'slug'
let activeFaq = this.faq.filter(obj => obj.items.filter(item => item.slug === 'slug'));
console.log(activeFaq.id);
This gives me an undefined. I should get 2729
There are multiple ways you could go about this. If you can use .flatMap, then one solution would be to flatten all items into a single array and then use .find:
const item = this.faq.flatMap(obj => obj.items).find(item => item.slug === 'slug')
However, flattening seems a bit unnecessary. An approach that avoid unnecessary computations would be a helper function with a boring loop:
function findItem(faqs, callback) {
for (const faq of faqs) {
const item = faq.find(callback);
if (item) {
return item;
}
}
}
const activeFaq = findItem(this.faq, item => item.slug === 'slug');
var activeFaq = this.faq.filter(obj => obj.items.some(item => item.slug === 'slug'))[0];
console.log(activeFaq.items[0].id); //2729
let activeFaq = this.faq.reduce( ( obj ) => {
const foundItem = obj.items.find( ( item ) => {
return item.slug === 'slug'
} )
if( foundItem ) {
acc = foundItem
}
return acc
}, null )
console.log(activeFaq.id);

Categories

Resources