Loop over object to run an axios query - javascript

I need to be able to execute await axios.post (api, data)
taking all the values of parameters
const parameters = {
userId: [ '2', '4' ],
categoryId: '2'
}
that is, all possible combinations: userId=2&categoryId=2 y userId=4&categoryId=2
What I have:
const data = {};
const api = url_api + "?" + "userId=" + userId + "&categoryId =" + categoryId;
const resp = await axios.post(api, data);
How can I do it?
And how would it be for the cases that parameters is:
const parameters = {
userId: [ '2', '4' ],
categoryId: [ '1', '6' ]
}
all possible combinations: userId=2&categoryId=1, userId=2&categoryId=6, userId=4&categoryId=1, userId=4&categoryId=6
Thanks!

I think you should use inner & outer loop for it.
if your data is like this, do below.
const parameters = {
userId: [ '2', '4' ],
categoryId: [ '1', '6' ]
};
const dataList = [];
parameters.userId.forEach(u => {
parameters.categoryId.forEach(c => {
dataList.push(`${url_api}?userId=${u}&categoryId=${c}`);
})
});
dataList.forEach(async(d) => {
const res = await axios.post(d, data);
...
});
and if your data can be like this, do below.
const parameters = {
userId: [ '2', '4' ],
categoryId: '3',
};
const dataList = [];
parameters.userId.forEach((u) => {
parameters.categoryId.length <= 1
? dataList.push(`${url_api}?userId=${u}&categoryId=${parameters.categoryId}`)
: parameters.categoryId.forEach((c) => {
dataList.push(`${url_api}?userId=${u}&categoryId=${c}`);
});
});
dataList.forEach(async(d) => {
const res = await axios.post(d, data);
...
});

Related

How to update the data inside the nested Array

I have data structure like this:
const data = [
{
question: 'string of question',
parentId: '1',
userChoice: 'Yes',
child: []
},
{
question: 'string of question',
parentId: '2',
userChoice: 'No',
child: [
{
id: 6,
sub_question: 'sub question',
weightage: 1
},
{
id: 7,
sub_question: 'sub question',
weightage: 1
},
{
id: 8,
sub_question: 'sub question',
weightage: 1
}
]
}
]
I'm able to handle the first layer of data without child array.
This is how I'm doing;
// states
const deviceReport = localStorage.getItem('deviceReport') ? JSON.parse(localStorage.getItem('deviceReport')) : []
const [data, setData] = useState(deviceReport)
const [childData, setChildData] = useState([])
// To Put user response via question param to data and then persist it with localStorage
const handleClickYes = (question) => {
// find if question is in the data array
const hasQuestion = data.find(({ parentId }) => question.id === parentId)
const indexOfQuestion = data.indexOf(hasQuestion)
// copy data to mutable object
let newData = [...data]
if (hasQuestion) {
// update the value with specific selected index in the array.
newData[indexOfQuestion] = {
question: question.if_yes,
parentId: question.id,
userChoice: 'YES',
child: []
}
} else {
// concat existing data with a new question
newData = [
...newData,
{
question: question.if_yes,
parentId: question.id,
userChoice: 'YES',
child: []
}
]
}
localStorage.setItem('deviceReport', JSON.stringify(newData))
setData(newData)
}
Similary Now I want to add the data into child array with similar logic like If child array has same key then it should not concate otherwise it should concate the child array
I tried following this method to build childData first then concate into data.child[]
But this is not working even to collect the user response
function subQuestionsHandler(sub) {
// const hasId = data.child.some(({ id }) => sub.id === id)
const id = sub.id
const sub_question = sub.sub_question
const weightage = sub.weightage
// console.log(id, sub_question, weightage)
const hasId = childData.find(({ id }) => sub.id === id)
if (!hasId) {
setChildData((childData) => childData.concat({ id: id, sub_question: sub_question, weightage: weightage }))
}
}
So how can I concate the child array inside the data array. ?
Array:
let data = [
{
id: 1,
question: "...",
children: [],
},
{
id: 2,
question: "...",
children: [
{
id: 1,
sub_question: "...",
},
{
id: 2,
sub_question: "...",
},
],
},
];
Concat array:
data = [...data];
data.push({
id: 3,
question: "concatenated",
children: [],
});
Update array:
const datumIndexToUpdate = 0;
data = [...data];
data[datumIndexToUpdate] = { ...data[datumIndexToUpdate] };
data[datumIndexToUpdate].question = "updated";
Concat sub-array:
const datumIndexToUpdate = 0;
data = [...data];
data[datumIndexToUpdate] = { ...data[datumIndexToUpdate] };
data[datumIndexToUpdate].children = [...data[datumIndexToUpdate].children];
data[datumIndexToUpdate].children.push({
id: 3,
sub_question: "concatenated",
});
Update sub-array:
const datumIndexToUpdate = 0;
const childIndexToUpdate = 0;
data = [...data];
data[datumIndexToUpdate] = { ...data[datumIndexToUpdate] };
data[datumIndexToUpdate].children = [...data[datumIndexToUpdate].children];
data[datumIndexToUpdate].children[childIndexToUpdate] = {
...data[datumIndexToUpdate].children[childIndexToUpdate],
};
data[datumIndexToUpdate].children[childIndexToUpdate].sub_question = "updated";
This is how you concat an array
[1].concat([3]) === [1, 3]
This is how you concat a nested array
const nest1 = [[1]]
const nest3 = [[3]]
nest3[0].concat(nest1[0]) // === [[3, 1]]
Now I suggest simplifying your scenario and applying this logic to it. Or change the title in your question

How to from array want to form a pattern to make a query to make API call

I want to derive a pattern from an array. The Array could be n number of elements
This is the Array pattern I receive from DB, (Note here elements could be n numbers)
[
{ id: '2', name: 'ONe' },
{ id: '3', name: 'Twop' },
{ id: '1', name: 'ThreeC' }
]
And I want to for a patter like AccountId=2&AccountId=3&AccountId=1 formed from the array and id in it
And I want to pass that formed data into the below URL as a query parameter to make an API call.
const config = {
method: 'get',
url: `${URL}api/cost?AccountId=1&AccountId=2&AccountId=3`,
headers: {
'Cookie': 'ARRAffinity=6f6eb54d3b6d7ed13173b9203b0bd6571b611d626818fba77a815805a7c90146'
},
data: data
};
const dataOutput = await axios(config )
.then(function (response) {
console.log(JSON.stringify(response.data));
return response.data;
})
.catch(function (error) {
console.log(error);
});
You can do it like this:
stackOverflow = () => {
let requestPartStr = '';
const data = [
{ id: '2', name: 'ONe' },
{ id: '3', name: 'Twop' },
{ id: '1', name: 'ThreeC' }
];
data.forEach((val, index) => {
requestPartStr += index !== data.length - 1
? `AccountId=${val.id}&`
: `AccountId=${val.id}`;
})
return requestPartStr;
};
Based on given code this can be a full code example:
const data = [
{ id: '2', name: 'ONe' },
{ id: '3', name: 'Twop' },
{ id: '1', name: 'ThreeC' }
];
getRequestParameters = (data) => {
let requestPartStr = '';
data.forEach((val, index) => {
requestPartStr += index !== data.length - 1
? `AccountId=${val.id}&`
: `AccountId=${val.id}`;
})
return requestPartStr;
};
const requestParameters = getRequestParameters(data);
const config = {
method: 'get',
url: `${URL}api/cost?${requestParameters}`,
headers: {
'Cookie': 'ARRAffinity=6f6eb54d3b6d7ed13173b9203b0bd6571b611d626818fba77a815805a7c90146'
},
data: data
};
const dataOutput = await axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
return response.data;
})
.catch(function (error) {
console.log(error);
});
Use map and join to build a params string
const data = [
{ id: "2", name: "ONe" },
{ id: "3", name: "Twop" },
{ id: "1", name: "ThreeC" },
];
const params = data.map(({ id }) => `AccountId=${id}`).join("&");
const url = `foo.com/api/cost?${params}`;
console.log(url);

Filtering array of objects if specific key contains search term

I am trying to filter through an object with multiple key/value pairs by a specific key. It appears that the code I've written is searching the entire object regardless of the key...
If key name contains the search term, return the search term.
Array of Objects:
export const someArrayOfObjects = [
{ id: '1', name: 'Something' },
{ id: '2', name: 'Another' },
{ id: '3', name: 'Lets do one more' },
]
Search:
const searchResults = someArrayOfObjects.filter((o) =>
Object.keys(o).some((k) => o[k].toString().toLowerCase().includes(searchTerm.toLowerCase()))
);
So if I search "Something", I only want it to loop through name to search for that term...
You don't need the Object.keys loop.
const someArrayOfObjects = [
{ id: '1', name: 'Something' },
{ id: '2', name: 'Another' },
{ id: '3', name: 'Lets do one more' },
];
let key = 'name';
let searchTerm = 'th';
const res = someArrayOfObjects.filter(o =>
o[key].toLowerCase().includes(searchTerm.toLowerCase()));
console.log(res);
similar to iota's, you don't need to create the extra array with Object.keys.
just loop/check every item inside the original array with the 'name' key.
you can also try to make it more reusable like below.
const someArrayOfObjects = [
{ id: '1', name: 'Something' },
{ id: '2', name: 'Another' },
{ id: '3', name: 'Lets do one more' },
];
const search = function (anyArray, searchTerm) {
return anyArray.filter((obj) => {
if (obj.name === searchTerm) {
return obj.name;
}
return false;
});
};
const case1 = search(someArrayOfObjects, 'Something');
console.log(case1);

Transform an array of data by status

I need to filter an array by property:
Here's the data, which I get from the server:
const mockResults = [
{
user: {
firstName: '1',
lastName: '1'
},
status: 'WRONG'
},
{
user: {
firstName: '2',
lastName: '2'
},
status: 'WRONG'
},
{
user: {
firstName: '3',
lastName: '3'
},
status: 'CORRECT'
}
];
To display the data, I need to transform it to a required by ReactNative SectionList format:
const requiredFormat = [
{
status: 'WRONG',
data: [{ user: {firstName: '1', lastName: '1'}}, { user: {firstName: '2', lastName: '2'}}],
},
{
status: 'CORRECT',
data: [{ user: {firstName: '3', lastName: '3'}}],
},
];
Basically, the mockResults should be sorted by status. There can be maximum of 4 statuses: correct, wrong, missed, chosen. All these statuses should include all the data marked with them.
What is the right way to implement this?
I've tried to filter the array, but I'm stuck at this point:
const transformArray = mockResults.filter(item => {
return {
answerStatus: item.status,
data: [item.user]
}
})
You may walk through the array (using Array.prototype.reduce() method) and create new element of resulting array once you see there's no such with current status or append current element data if one exists:
const mockResults = [{user:{firstName:'1',lastName:'1'},status:'WRONG'},{user:{firstName:'2',lastName:'2'},status:'WRONG'},{user:{firstName:'3',lastName:'3'},status:'CORRECT'}],
result = mockResults.reduce((r,{status, ...rest}) => {
const common = r.find(e => e.status == status)
common ?
common.data.push(rest) :
r.push({status, data:[rest]})
return r
}, [])
console.log(result)
.as-console-wrapper {min-height:100%}
You can use reduce() to achieve that:
const mockResults = [{user: { firstName: '1', lastName: '1'}, status: 'WRONG'},{user: {firstName: '2',lastName: '2'},status: 'WRONG'},{user: { firstName: '3',lastName: '3'},status: 'CORRECT'}];
const result = mockResults.reduce((a, {user, status}) => {
const temp = a.find(e => e.status === status);
if (temp) {
temp.data.push({user});
} else {
a.push({status, data: [{user}]});
}
return a;
}, []);
console.log(result);
Read from the Array.prototype.reduce() documentation:
The reduce() method executes a reducer function (that you provide) on each element of the array, resulting in a single output value.
I hope that helps!
You can reduce the array onto an object with its keys being the status property and its value an array of users with that status. Then, map over the entries to turn it back into an array of objects.
Note: The reduce function is creating a new object (accumulator) at each index. This is probably not practical for large data sets as it would be really slow.
const toSectionList = results =>
Object.entries(
results.reduce(
(obj, { user, status }) => ({
...obj,
[status]: [...(obj[status] || []), { user }],
}),
{}
)
).map(([status, data]) => ({ status, data }))
// example use:
const requiredFormat = toSectionList(mockResults)
The reduce function in this one modifies the accumulator object instead of creating a new one. It should preform better with larger data sets.
const toSectionList = results =>
Object.entries(
results.reduce((obj, { user, status }) => {
obj[status] = obj[status] || []
obj[status].push({ user })
return obj
}, {})
).map(([status, data]) => ({ status, data }))
That's what I did.
const mockResults = [
{
user: {
firstName: '1',
lastName: '1'
},
status: 'WRONG'
},
{
user: {
firstName: '2',
lastName: '2'
},
status: 'WRONG'
},
{
user: {
firstName: '3',
lastName: '3'
},
status: 'CORRECT'
}
]
function format(data) {
const resultDict = {}
for (let i of data) {
if (!resultDict[i.status]) {
resultDict[i.status] = { data: [] }
}
resultDict[i.status].data.push(i)
delete resultDict[i.status].data[resultDict[i.status].data.length - 1].status
}
const result = []
for (let i in resultDict) {
const res = {
status: i,
data: resultDict[i].data
}
result.push(res)
}
return result
}
console.log(format(mockResults))

map object.keys into string from array of objects

I have an array, this for example:
interface: [
{ _id: '1', name: 'Foo' },
{ _id: '2', name: 'bar },
{ _id: '3', name: 'boo}
]
i'd now like to map this to a single string ->
this.dataSource.data = data.data.map(item => ({
interface: item.interfaces.name,
}));
so that the result inside the dataSource.data.interface looks like 'Foo, bar, boo'
You could map the name property and join the array.
var data = { interface: [{ _id: '1', name: 'Foo' }, { _id: '2', name: 'bar' }, { _id: '3', name: 'boo' }]};
data.interface = data.interface.map(({ name }) => name).join(', ');
console.log(data);
Use Array.prototype.reduce:
const concatString = data.interface.reduce((acc, value, index, arr) => {
const str = index !== arr.length - 1 ? `${value.name}, ` : value.name;
return acc += str;
}, "");

Categories

Resources