I want check whether document front and back object is present in an array. If both
front and back object is present set document to true or if only front is present set document to false
const [document, setDocument] = useState('');
let data = [
{ id: 1, type:'document', frontBack:'front'},
{ id: 2, type:'pan', frontBack:'front'},
{ id: 3, type:'profile', frontBack:'front'},
{ id: 4, type:'document', frontBack:'back'},
];
You can check if data has a frontBack:'front' with this code:
data.find(({type, frontBack})=> type == 'document' && frontBack == 'front')
And you can check if data has a frontBack:'back' with this code:
data.find(({type, frontBack})=> type == 'document' && frontBack == 'back')
If both expressions return an object, you have both.
If any of them return undefined, you don't.
There are multiple approaches to solving this problem, but you could make use of .some() method to check if the criteria mentioned above are satisfied or not.
setDocument(data.some(item=>item.frontBack === 'front') && data.some(item=>item.frontBack === 'back'))
.some() returns true if one or more items in the iterable returns true, so we are checking if both front and back exists, and using the conditional && we can say if both the items exist or not and set the state accordingly. You can also make the code more understandable by extracting the logical operation result into a separate variable, like so:
const res = data.some(item=>item.frontBack === 'front') && data.some(item=>item.frontBack === 'back')
setDocument(res)
I tried to write it out in as straightforward a way as possible. I wasn't sure which variable you meant to set, so I used one called setDoc:
//const [document, setDocument] = useState('');
let data = [
{ id: 1, type:'document', frontBack:'front'},
{ id: 2, type:'pan', frontBack:'front'},
{ id: 3, type:'profile', frontBack:'front'},
{ id: 4, type:'document', frontBack:'back'},
];
let setDoc, front, back = false
data.forEach(obj => {
if(obj.type === 'document' && obj.frontBack === 'front') {
front = true
}
if(obj.type === 'document' && obj.frontBack === 'back') {
back = true
}
})
setDoc = front && back
console.log(setDoc)
You can use some method of Array object, which returns true if some of the elements pass the given test.
let data = [{
id: 1,
type: 'document',
frontBack: 'front'
},
{
id: 2,
type: 'pan',
frontBack: 'front'
},
{
id: 3,
type: 'profile',
frontBack: 'front'
},
{
id: 4,
type: 'document',
frontBack: 'back'
},
];
let out = data.some(d => d.type == "document" && d.frontBack == "front") && data.some(d => d.type == "document" && d.frontBack == "back");
console.log(out);
Related
How to loop through an array of object got similar key and different value for Example if,
arrayOfObjects = [
{ parent: 'relatedParty', child: 'role === CEO', andOr = '&&' }
{ parent: 'relatedParty', child: 'name === Arun' , andOr = '||'}
{ parent: 'relatedParty', child: ' id === 123', andOr = '&&' }
{ parent: 'cusotm', child: 'contact === DAP', andOr = '||' }
{ parent: 'custom', child: 'team==dap', andOr = '&&' }
{ parent: 'multiple', child: 'key ===keys', andOr = '||' }
{ parent: 'multiple', child: 'value=== values', andOr = '&&' }
].
im stuck in a position where how can i iterate through this and get output like if
first object of parent is === second object, then I want them to add into an array and finally those values should be inside another array
[[role === CEO && name === Arun && id === 123 &&], [contact === DAP || team==dap && ],[ key ===keys || value=== values &&]]
Your example is not a valid array, are you getting it from somewhere else, like a http request?
Anyway, after fixing it to a valid array, you can try grouping by parent, and them mapping the values into what you need.
Grouping could be like:
const grouped = {}
arrayOfObjects.forEach(obj => {
if (!grouped[obj.parent]) {
grouped[obj.parent] = []
}
grouped[obj.parent].push(obj)
})
You can also use reduce, or other ways to group by parent.
After it, just map the values into what you want:
const result = Object.values(grouped).map(group => {
return group.map(obj => `${obj.child} ${obj.andOr}`).join(' ')
})
If you need it in string format to send to some api, do it like:
const body = JSON.stringify(result)
Here is a more concise way to handle your problem:
const arrayOfString = arrayOfObjects.reduce((acc, {parent, child, andOr}) => {
const value = `${child} ${andOr}`
acc[parent] = acc[parent] ? [`${acc[parent] || ''} ${value}`] : [`${value}`]
return acc
}, {})
const result = Array.from(Object.values(arrayOfString))
function Ha8(arr, id) {
let result = [];
for(let i = 0; i < arr.length; i++) {
if(Array.isArray(arr[i].children)) {
// if it is a array, it going to be run recursive
result.push(arr[i].children)
const col = Ha8(result[i], id);
if(col === id) {
// find it in array in array
return result
// then return the id object,
} else {
continue; // still can't find.. go ahead!
}
} else if (arr[i]['id']===id) {
return arr[i] // will return valid id object
}
return null // if its none , return null, or parameter id is undefined.
}
}
I m write Intended direction. but its not work..
how can i fix ? give me some tip please.
let input = [
{
id: 1,
name: 'johnny',
},
{
id: 2,
name: 'ingi',
children: [
{
id: 3,
name: 'johnson',
},
{
id: 5,
name: 'steve',
children: [
{
id: 6,
name: 'lisa',
},
],
},
{
id: 11,
},
],
},
{
id: '13',
},
];
output = Ha8(input, 5);
console.log(output); // --> { id: 5, name: 'steve', children: [{ id: 6, name: 'lisa' }] }
output = Ha8(input, 99);
console.log(output); // --> null
I wanna return like that, but only return 'null' ..
need to check children's id and return children's object by using recursive.
so i write like that. but i have no idea..
how to return correctly children id's element?
I will give you an answer using a totally different approach, and using the magic of the JSON.stringify() method, more specifically the replacer optional parameter, which allows the use of a callback function that can be used as a filter.
As you can see, it simplifies a lot the final code. It could also be modified to introduce not only an id, but also any key or value, as I did in my final approach.
EDIT: Following your suggestion, as you prefer your function to be recursive, I recommend you to use the Array.reduce() method. It allows an elegant iteration through all the properties until the needs are met.
Using null as initial value, which is the last argument of the reduce method, it allows to iterate through all fields in the array in the following way:
The first if will always be skipped on the first iteration, as the initial value is null.
The second if will set the currentValue to the accumulator if the property id exists and is equal to the value you are trying to find
The third if, which you could add an Array.isArray() to add a type validation, will check if the property children exists. As it is the last one, it will only work if all the other conditions aren't met. If this property exists, it will call again Ha8Recursive in order to start again the process.
Finally, if neither of this works, it should return null. The absence of this last condition would return undefined if the input id doesn't exist
const Ha8 = (array, inputKey, inputValue) => {
let children = null;
JSON.stringify(array, (key, value) => {
if (value[inputKey] && value[inputKey] === inputValue) {
children = value;
}
return value;
});
return children;
};
const Ha8Recursive = (array, inputKey, inputValue) => {
return array.reduce((accumulator, currentValue) => {
if (accumulator) {
return accumulator;
} else if (currentValue[inputKey] && currentValue[inputKey] === inputValue) {
return currentValue;
} else if (currentValue.children) {
return Ha8Recursive(currentValue.children, inputKey, inputValue);
} else {
return null;
}
}, null)
}
const input = [{"id":1,"name":"johnny"},{"id":2,"name":"ingi","children":[{"id":3,"name":"johnson"},{"id":5,"name":"steve","children":[{"id":6,"name":"lisa"}]},{"id":11}]},{"id":"13"}];
console.log('JSON stringify function');
console.log(Ha8(input, 'id', 5));
console.log('Recursive function')
console.log(Ha8Recursive(input, 'id', 5));
Suppose the following array of objects is returned from an API:
const data = [
{ // first item
meta: {
stems: [
"serpentine",
"serpentinely"
]
},
hwi: {
hw: "sep*pen*tine",
prs: [
{
mw: "ˈsər-pən-ˌtēn",
sound: {
audio: "serpen02"
}
},
]
},
shortdef: [
"of or resembling a serpent (as in form or movement)",
"subtly wily or tempting",
"winding or turning one way and another"
]
},
{ // second item
meta: {
stems: [
"moribund",
"moribundities",
"moribundity"
]
},
hwi: {
hw: "mor*i*bund",
},
fl: "adjective"
}
]
I want to create a function that will generate a new array of objects. The objects in this new array will consist of data from the old objects, just rearranged. This is how I expect a new array to look, for example:
[
{
word: 'serpentine',
definitions: [
'of or resembling a serpent (as in form or movement)',
'subtly wily or tempting',
'winding or turning one way and another'
]
},
{
word: 'moribund',
definitions: [
'being in the state of dying : approaching death',
'being in a state of inactivity or obsolescence'
],
partOfSpeech: 'adjective'
}
]
I do this with the following function:
const buildNewData = arr => {
const newData = []
arr.forEach(item => {
newData.push({
...item.meta.stems[0] && { word: item.meta.stems[0]},
...item.shortdef && { definitions: item.shortdef },
...item.fl && { partOfSpeech: item.fl },
...item.hwi.prs[0].mw && { pronunciation: item.hwi.prs[0].mw}
})
})
return newData
}
buildNewData(data)
You may be curious as to why I use ...item.meta.stems[0] && { word: item.meta.stems[0]} in the creation of the new objects. This is to check if the property exists in the original object. If it doesn't exist, the expression will evaluate to false and therefore not be added to the new object. The first object in the original array does not have the fl property, so it evaluates to false when the new object is being constructed.
But this doesn't work when looking up a property that is an array. The code above fails with the error: TypeError: Cannot read property '0' of undefined. That's because the second item does not have a prs array under the hwi property, so the lookup fails.
Since I cannot control what data is returned from the API, how do I write a function that successfully creates a new array of objects in the format I've specified, without causing an error? I already have a solution to not add particular properties if they do not exist, but how do I take into account arrays?
More generally, I'm curious if there is a standardized way of extracting data from objects programmatically that prevents errors like this from occurring. Is there a better way to do this?
You need an additional guard so:
...item.hwi.prs[0].mw && { pronunciation: item.hwi.prs[0].mw}
becomes
...(Array.isArray(item.hwi.prs) && item.hwi.prs[0].mw) && { pronunciation: item.hwi.prs[0].mw}
which can be shortened to:
...(item.hwi.prs && item.hwi.prs[0].mw) && { pronunciation: item.hwi.prs[0].mw}
if you are confident that if item.hwi.prs exists its value will be an array that has a 0 value that can be spread.
const data = [
{ // first item
meta: {
stems: [
"serpentine",
"serpentinely"
]
},
hwi: {
hw: "sep*pen*tine",
prs: [
{
mw: "ˈsər-pən-ˌtēn",
sound: {
audio: "serpen02"
}
},
]
},
shortdef: [
"of or resembling a serpent (as in form or movement)",
"subtly wily or tempting",
"winding or turning one way and another"
]
},
{ // second item
meta: {
stems: [
"moribund",
"moribundities",
"moribundity"
]
},
hwi: {
hw: "mor*i*bund",
},
fl: "adjective"
}
];
const buildNewData = arr => {
const newData = []
arr.forEach(item => {
newData.push({
...item.meta.stems[0] && { word: item.meta.stems[0]},
...item.shortdef && { definitions: item.shortdef },
...item.fl && { partOfSpeech: item.fl },
...(Array.isArray(item.hwi.prs) && item.hwi.prs[0].mw) && { pronunciation: item.hwi.prs[0].mw}
})
})
return newData
}
let newData = buildNewData(data);
console.log(newData);
As you need to check existence of properties in an Object:
Use Optionnal chaining: https://javascript.info/optional-chaining
It returns a type undefined if the prop doesn't exist (but not string "undefined" ;) )
For desired order in new array, add numbers before the names of props.
let newData = [];
for (let i = 0; i < data.length; i++) {
newData[i] = {};
if (data[i]?.meta?.stems[i] != undefined)
newData[i].word = data[i].meta.stems[i];
if (data[i]?.shortdef != undefined) {
newData[i].definitions = data[i].shortdef.join(', ') + '.';
newData[i].definitions = newData[i].definitions.charAt(0).toUpperCase() + newData[i].definitions.substring(1); // Capitalize first letter
}
if (data[i]?.fl != undefined)
newData[i].partOfSpeech = data[i].fl;
}
console.log(...newData);
i have an API Laravel response such this:
{
id:1,
name: "Text",
category: {
id: 1,
name: "Text 2",
},
tags:[
{
id: 1,
name: "Tag1",
},
{
id: 2,
name: "Tag2",
},
],
},
For my front-end (with vuejs) i've created a simple computed function to filter the category, based on the user's selection of checkboxes.
checkedCategory: []
.
.
let posts = this.posts;
if (typeof this.checkedCategory !== 'undefined' && this.checkedCategory.length > 0) {
posts = posts.filter((post) => {
return this.checkedCategory.indexOf(post.category.name) > -1;})}
Everything works.Posts are filtered by the categories chosen by the user.
But, posts can also have several tags.
Is an array of objects, so i reformulated the block with an .includes (instead of .filter), but it returns an empty result.
checkedTags: []
.
.
let posts = this.posts;
if (typeof this.checkedTags !== 'undefined' && this.checkedTags.length > 0) {
posts = posts.includes((post) => {
return this.checkedTag.indexOf(post['tags']) > -1;})}
I think this should work:
let posts = this.posts;
if (typeof this.checkedTags !== 'undefined' && this.checkedTags.length > 0) {
posts = posts.filter(post => {
return post.tags.some(tag => checkedTags.includes(tag.name))
})
}
Basically it will just filter all the posts where at least one tag is in the checkedTags array. Depending on your needs you can also check if all the tags of the post are there with post.tags.every()
I am making a service call where I get back some data. For example:
var response = [
{id: 1, name: 'text1'},
{id: 2, name: 'text2'}
];
This array represents the most possible data I could get back. In other instances I may get back an empty array, an array with only one of those objects(either or of the objects inside the array).
I'd like to somehow loop through my array and check the id of each on=bject to set a flag for the front end to display other data. How do I properly do checks for the id's in the array for the scenarios I mentioned above?
Use Array.some()
var response = [{ id: 1, name: "text1" }, { id: 2, name: "text2" }];
var exists = (id, arr) => arr.some(e => e.id === id);
var id1Exists = exists(1, response);
var id2Exists = exists(2, response);
var id3Exists = exists(3, response);
console.log({ id1Exists, id2Exists, id3Exists });
var response = [
{id: 1, name: 'text1'},
{id: 2, name: 'text2'}
];
let flag
response.length > 0 && response.forEach(el => {
// JUST CHECKING IF ID IS PRESENT AND EQUAL TO 1
// YOU CAN CHANGE ACCORDINGLY
flag = el.id && el.id === 1 ? true : false
})
console.log(flag)
Here I write a function to find a certain object inside your array, I think this must help you:
public function getMyId($myArray, $id)
{
foreach($myArray as $key => $element){
$arrayFromObject = (Array) $element;
foreach($arrayFromObject as $keyObject => $valueObject){
if($valueObject['id'] == $id)
{
return $myArray[$key]->$keyObject;
}
}
}
return null;
}
For each element inside your array I convert object to array to verify if its id is equal to id u're looking for, than I return the array at certain position and certain value, or if you prefer u could just return the $valueObject it will be an array. I hope help u;