Why object is getting returned when applied map and filter to match the string search in available nested json data - javascript

I am returning the objects which have the card titles matches with the searched value from available data.
Data JSON :
let state = {rawData : [
{
"id": 1,
"title": "To Do",
"cards": [
{
"id": 111,
"title": "Team Meeting"
},
{
"id": 112,
"title": "DB Design"
}
]
},
{
"id": 2,
"title": "Doing",
"cards": [
{
"id": 221,
"title": "Raman's Review"
},
{
"id": 222,
"title": "Sequence Diagram"
}
]
},{
"id": 3,
"title": "Done",
"cards": [
{
"id": 331,
"title": "Karan's Review"
},{
"id": 332,
"title": "Karan"
}
]
}
]}
Here, As you can see rawData consist 3 objects each have cards array object.
Now, filter out the cards data which had a consist the search value. Please refer below code. To know how I am trying filter it and actual output I am getting Also the output I want.
var searchVal = "K"
let val = state.rawData.map(list => {
let out = list.cards.filter(card => card.title.toLowerCase().includes(searchVal.toLowerCase()))
let x = {...list}
x.cards =[...out]
console.log(x)
return x;
})
console.log(val)
As you can see above. I have a search str as "K". I am mapping over the each rawData object and using filter checking if the value is entered search string is available in card.title or not.
console result of x:
{ id: 1, title: 'To Do', cards: [] }
{ id: 2, title: 'Doing', cards: [] }
{
id: 3,
title: 'Done',
cards: [ { id: 331, title: "Karan's Review" }, { id: 332, title: 'Karan' } ]
}
Here, I am getting the result I want. But when I returns the x. The output is below:
[
{ id: 1, title: 'To Do', cards: [] },
{ id: 2, title: 'Doing', cards: [] },
{ id: 3, title: 'Done', cards: [ [Object], [Object] ] }
]
Please not here the cards are returned as objects. Not sure why this is happening.
The result I want :
[
{ id: 1, title: 'To Do', cards: [] }
{ id: 2, title: 'Doing', cards: [] }
{
id: 3,
title: 'Done',
cards: [ { id: 331, title: "Karan's Review" }, { id: 332, title: 'Karan' } ]
}
]
I need some help in understanding the reason behind/way around to resolve the issue.

Related

React Js array manipulation

hope you are doing fine
i came across to a problem of data array manipulation at starting there was not much manipulation required as work progressed now more data manipulation is required and i am running short on this(as a fresher early days of my career
problem explanation - as data i am receiving an array of object and each object contains another array of information (key-value pair) and that array also contains another array of information(key value pair ) and requirement is to i have to loop main data object-item with respect to length of deep nested array and display them on front except this i have done the most part.
i am attaching a sample code of my problem below i am requesting you guys to provide solution for this issue
`
import React, { useState } from "react";
const data = [
{
id: 1,
name: "Something Goes here",
address: "Earth",
arr1: [
{
newId: 1,
title: "Title 1",
midName: "Nothing",
arr2: [
{
subId: 1,
goes: "Hello",
ollo: "Not what you think",
},
{
subId: 2,
goes: "Hello 2",
ollo: "Not what you",
},
],
},
],
},
{
id: 2,
name: "Something Goes",
address: "Mars",
arr1: [
{
newId: 3,
title: "Title sddsdsad",
midName: "Nothing",
arr2: [
{
subId: 2,
goes: "Hello adasdasdasd",
ollo: "Not what you think asdasdasdawd",
},
{
subId: 2,
goes: "Hello 2",
ollo: "Not what you asdasasd",
},
],
},
],
},
];
const App = () => {
const [dummy, setDummy] = useState([]);
let dummyArr = [],
tempObj,
temp;
const tempFunc = () => {
for (let i = 0; i < data.length; i++) {
for (let j = 0; j < data[i].arr1; j++) {
for (let k = 0; k < data[i].arr1[j].arr2; k++) {
temp = data[i].arr1[j].arr2[k];
delete data[i].arr1[j].arr2[k];
tempObj = { ...temp ,...data[i], };
dummyArr.push(tempObj);
tempObj = {};
console("tempObj -->", tempObj);
}
}
}
};
console.log("dummyArr", dummyArr);
return (
<React.Fragment>
<button>Hello oooo</button>
</React.Fragment>
);
};
export default App;
expected result is to have both arrays pushed into main itemObject
`
const sampleArray = [
{
id: 2,
name: "Something Goes",
address: "Mars",
newId: 3,
title: "Title sddsdsad",
midName: "Nothing",
subId: 2,
goes: "Hello adasdasdasd",
ollo: "Not what you think asdasdasdawd",
},
];
This code can help you achieve a nested level of any key array and make its single level of array list with extract the keys of non-array value.
The above answer is only limited to nested, but this code is not limited to level what you have and what key has an array value it will iterate and n level of tress
Thanks
const data = [
{
id: 1,
name: "Something Goes here",
address: "Earth",
arr1: [
{
newId: 1,
title: "Title 1",
midName: "Nothing",
arr2: [
{
subId: 1,
goes: "Hello",
ollo: "Not what you think",
},
{
subId: 2,
goes: "Hello 2",
ollo: "Not what you",
},
],
},
],
},
{
id: 2,
name: "Something Goes",
address: "Mars",
arr1: [
{
newId: 3,
title: "Title sddsdsad",
midName: "Nothing",
arr2: [
{
subId: 2,
goes: "Hello adasdasdasd",
ollo: "Not what you think asdasdasdawd",
},
{
subId: 2,
goes: "Hello 2",
ollo: "Not what you asdasasd",
},
],
},
{
newId: 4,
title: "Title sddsdsad1",
midName: "Nothing",
arr2: [
{
subId: 2,
goes: "Hello adasdasdasd",
ollo: "Not what you think asdasdasdawd",
},
{
subId: 2,
goes: "Hello 2",
ollo: "Not what you asdasasd",
},
],
},
],
},
];
function getArrayHasValue(obj) {
const keys = Object.keys(obj).filter(accu => Array.isArray(obj[accu]))
return keys[0] ? keys[0] : null;
}
function getObjecNoNested(obj) {
const keys = Object.keys(obj).filter(accu => !Array.isArray(obj[accu]))
return keys
}
function unwindArray(arr, queue,ref) {
for (let i of arr) {
const nestedArrayKayname = getArrayHasValue(i)
const nonNestedKeys = getObjecNoNested(i)
ref = JSON.parse(JSON.stringify(ref))
if (nestedArrayKayname) {
nonNestedKeys.forEach(elem => {
ref[`${elem}`] = i[elem]
})
unwindArray(i[nestedArrayKayname], queue, ref)
}else {
nonNestedKeys.forEach(elem => {
ref[`${elem}`] = i[elem]
})
queue.push(ref)
}
}
return queue
}
console.log(unwindArray(data, [],{}))
Try this
const yourData = [
{
id: 1,
name: "Something Goes here",
address: "Earth",
arr1: [
{
newId: 1,
title: "Title 1",
midName: "Nothing",
arr2: [
{
subId: 1,
goes: "Hello",
ollo: "Not what you think",
},
{
subId: 2,
goes: "Hello 2",
ollo: "Not what you",
},
],
},
],
},
{
id: 2,
name: "Something Goes",
address: "Mars",
arr1: [
{
newId: 3,
title: "Title sddsdsad",
midName: "Nothing",
arr2: [
{
subId: 2,
goes: "Hello adasdasdasd",
ollo: "Not what you think asdasdasdawd",
},
{
subId: 2,
goes: "Hello 2",
ollo: "Not what you asdasasd",
},
],
},
],
},
];
const tempFunc = (yourData) => {
const result = [];
for(let data of yourData){
const temp ={...data, ...data.arr1[0], ...data.arr1[0].arr2[data.arr1[0].arr2.length-1]};
delete temp.arr1;
delete temp.arr2;
result.push(temp);
}
return result;
};
console.log(tempFunc(yourData));

Javascript: How to filter object in array

I have an array that is consisted of object which has categoryName(string) field and an array(plants).
I'd like to filter using plant name, what's the best approach?
I tried with but it only returns plants array, ignores categoryName
this.itemList.map(item => item.plants.filter(p=> p.name.toLowerCase().includes(this.searchTerm.toLowerCase())));
Structure
[
[
categoryName: "Heating"
plants: Array(2)
0: {plantId: 35, name: "Alston Oven", description: "Oven", plantCategoryId: 2, whenCreated: "1519357215942", …}
1: {plantId: 19, name: "Gregs Oven", description: null, plantCategoryId: 2, whenCreated: "1516830724579", …}
]
[
categoryName: "Refrigeration"
plants: Array(4)
0: {plantId: 13, name: "Fridge 1 ", description: "Walk in fridge" …}
1: {plantId: 5, name: "Fridge 2 Updated", description: "Description of Fridge 2" …}
2: {plantId: 4, name: "Fridge"....}
]
]
Try:
this.itemList.map(function(a) {
return {
categoryName: a.categoryName,
plants: a.plants.filter(p => p.name.toLowerCase().includes(this.searchTerm.toLowerCase()))
}}).filter(a => a.plants.length > 0)
Use filter() on the outer array and some() on the inner plants array.
This will not filter out the specific plant(s) within the plants array but keep the whole array intact. It is not clear whether you need to filter the sub array or not
const term = this.searchTerm.toLowerCase(),
res = this.itemList.filter(({plants}) => plants.some(({name}) => name.toLowerCase().includes(term)))
Please try this example
const searchTerm = "Alston";
const itemList = [
{
categoryName: "Heating",
plants: [
{
plantId: 35,
name: "Alston Oven",
description: "Oven",
plantCategoryId: 2,
whenCreated: "1519357215942",
},
{
plantId: 19,
name: "Gregs Oven",
description: null,
plantCategoryId: 2,
whenCreated: "1516830724579",
},
],
},
{
categoryName: "Refrigeration",
plants: [
{ plantId: 13, name: "Fridge 1 ", description: "Walk in fridge" },
{
plantId: 5,
name: "Fridge 2 Updated",
description: "Description of Fridge 2",
},
{ plantId: 4, name: "Fridge" },
],
},
];
const output = itemList.filter((item) => {
return item.plants
.map((entry) => entry.name.toLowerCase())
.join()
.includes(searchTerm.toLowerCase());
});
console.dir(output, { depth: null, color: true });
See
Array.prototype.map()
Array.prototype.filter()
Array.prototype.join()
If you just want to filter the plants arrays, you don't need to use map. Use forEach(), and then reassign the plants property with the filtered array there.
this.itemList.forEach(item =>
item.plants = item.plants.filter(p =>
p.name.toLowerCase().includes(this.searchTerm.toLowerCase())));

Constructing Tree View Object

I'd like to construct an Array Object for tree view in React Native.
Realm DB returns following rows as they have parent-child relation:
{
"0":{
"ID":3,
"name":"KITCHEN",
"parentID":2,
"createdBY":null,
"createdAT":null
},
"1":{
"ID":4,
"name":"BATHROOM",
"parentID":2,
"createdBY":null,
"createdAT":null
},
"2":{
"ID":5,
"name":"OIL",
"parentID":3,
"createdBY":null,
"createdAT":null
},
"3":{
"ID":6,
"name":"LIQUID",
"parentID":5,
"createdBY":null,
"createdAT":null
},
"4":{
"ID":7,
"name":"SOLID",
"parentID":5,
"createdBY":null,
"createdAT":null
}
}
Object should be look like this:
const treeData = [
{
key: 3,
label: 'KITCHEN',
nodes: [
{
key: '5',
label: 'OIL',
nodes: [
{
key: '6',
label: 'LIQUID',
},
{
key: '7',
label: 'SOLID',
},
],
},
],
},
{
key: 4,
label: 'BATHROOM',
},
];
My attempt was looping over all rows and get their IDs then in a nested loop checking the parentID with the ID and if any match occurs then adding that node to another object.
This only gives me the child/s of any parent.
for (var i = 0; i < rows.length; i++) {
let tempID = rows[i].ID
treeData = treeData.concat(rows[i])
for (var j = 0; j < rows.length; j++) {
let tempParentID = rows[j].parentID
if (tempID == tempParentID) {
subCategoryJson = subCategoryJson.concat(rows[j])
}
}
}
Problem is I am really not sure how to construct exactly the above Array Object.
PS. I'm trying to use following node module: https://www.npmjs.com/package/react-simple-tree-menu
You could store the keys and filter the parentt nodes for the result.
var data = { 0: { ID: 3, name: "KITCHEN", parentID: 2, createdBY: null, createdAT: null }, 1: { ID: 4, name: "BATHROOM", parentID: 2, createdBY: null, createdAT: null }, 2: { ID: 5, name: "OIL", parentID: 3, createdBY: null, createdAT: null }, 3: { ID: 6, name: "LIQUID", parentID: 5, createdBY: null, createdAT: null }, 4: { ID: 7, name: "SOLID", parentID: 5, createdBY: null, createdAT: null } },
tree = function (data) {
var t = {},
parents = {};
Object.values(data).forEach(({ ID: key, name: label, parentID }) => {
Object.assign(t[key] = t[key] || {}, { key, label });
t[parentID] = t[parentID] || { };
t[parentID].nodes = t[parentID].nodes || [];
t[parentID].nodes.push(t[key]);
parents[key] = true;
});
return Object
.keys(t)
.filter(k => !parents[k])
.flatMap(k => t[k].nodes);
}(data);
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I would first loop and create a look up object so it is easy to reference parents and check if a parent exists.
After that I would loop over the data again and check to see if it has a parent, if it does, add a nodes property and push the element to it. If not add to the parent node.
const data = {
"0": {
"ID": 3,
"name": "KITCHEN",
"parentID": 2,
"createdBY": null,
"createdAT": null
},
"1": {
"ID": 4,
"name": "BATHROOM",
"parentID": 2,
"createdBY": null,
"createdAT": null
},
"2": {
"ID": 5,
"name": "OIL",
"parentID": 3,
"createdBY": null,
"createdAT": null
},
"3": {
"ID": 6,
"name": "LIQUID",
"parentID": 5,
"createdBY": null,
"createdAT": null
},
"4": {
"ID": 7,
"name": "SOLID",
"parentID": 5,
"createdBY": null,
"createdAT": null
}
}
const values = Object.values(data)
const lookup = values.reduce((obj, entry) => ({
[entry.ID]: entry,
...obj
}), {})
const result = values.reduce((arr, entry) => {
const parent = lookup[entry.parentID]
if (parent) {
parent.nodes = parent.nodes || []
parent.nodes.push(entry)
} else {
arr.push(entry)
}
return arr
}, [])
console.log(result)

Javascript compare two JSON arrays and return key of the unmatched value

I have two JSON arrays, would like to know the key which don't match. I don't need the value.
Example:
livetable: [
{ id: 1, name: "Sandra" },
{ id: 2, name: "John" },
],
backupTable: [
{ id: 1, name: "Sandra" },
{ id: 2, name: "Peter" },
],
I can get the key/value pair which is diffrent with this Lodash script:
difference = _.differenceWith(livetable,backupTable,_.isEqual)
But I would just need the key, in this example "name" for "id: 2" is not matching, so I would need to get the "name" key to new array/variable.
(Using VUE CLI)
EDIT: Added example of current code output.
var livetable = [{"id": 1, "name": "Sandra", "id": 2, "name": "John"}]
var backupTable = [{"id": 1, "name": "Sandra", "id": 2, "name": "Peter"}]
console.log(_.differenceWith(backupTable,livetable,_.isEqual))
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.15/lodash.min.js"></script>
This will output the key:value pair, but I would just need the key which is diffrent.
I think I understand what you're trying to do. There are some unknowns though, like what should happen if there is a missing record in the second data set?
This solution assumes each table of data has the same amount of records and the records have the same IDs.
// define data
const livetable = [
{ id: 1, name: "Sandra" },
{ id: 2, name: "John" }
]
const backupTable = [
{ id: 1, name: "Sandra" },
{ id: 2, name: "Peter" }
]
const getDifferentRecordsByID = (sourceRecords, compareRecords) => {
// simple utility function to return a record object matching by ID
const findComparisionRecord = id => compareRecords.find(compareRecord => compareRecord.id === id)
// using the utility function, we can filter out any mismatching records by comparing name
return sourceRecords
.filter(sourceRecord => sourceRecord.name !== findComparisionRecord(sourceRecord.id).name)
// then map over all the records and just pull out the ID
.map(record => record.id)
}
console.log(getDifferentRecordsByID(livetable, backupTable)) // [2]
Here is working VUE code for my problem.
Function returns [ "name" ], which is exactly what I need.
data() {
return {
livetable: [{ id: 1, name: "Sandra" },{ id: 2, name: "John" }],
backupTable: [{ id: 1, name: "Sandra" },{ id: 2, name: "Peter" }],
difColumns: null,
};
},
methods: {
test3() {
let resultArray = []
this.livetable.forEach((array1, index) => {
const array2 = this.backupTable[index];
resultArray.push(this._.reduce(array1, (result, value, key) => this._.isEqual(value, array2[key]) ? result : result.concat(key), []))
});
this.difColumns = resultArray[0]
}
},

How to define schema for recursive model with Normalizr

Having a bit of an issue trying to normalise a payload, that contains a nested schema of the same type as the parent using Normalizr
For example I have the initial object (menu) which has a child (sections) which is an array of objects (section), which can go n deep.
{
id: 123,
sections: [{
id: 1,
sections:[{ id: 4, sections: [ id: 5, sections: [] ] }]
}, {
id: 2,
sections:[]
}, {
id: 3,
sections:[]
}]
}
I started by creating a menu schema, that had sections in the definition that linked to a sections schema, that worked for the first pass, but then wouldn't handle children of sections, so I added a subsequent definition within the section schema with the same name (was worth a shot) but it didn't work.
const section = new schema.Entity('sections')
const sections = new schema.Entity('sections', {
sections: section
})
const menu = new schema.Entity('menu', {
sections: [ sections ]
})
section.define({ sections })
I'm hoping to end up with the object below:
{
entities: {
menu: {
sections: [1, 2, 3]
},
sections: [{
1: { id: 1, sections: [4] },
2: { id: 2, sections: [] },
3: { id: 3, sections: [] },
4: { id: 4, sections: [5] },
5: { id: 5, sections: [] },
}]
}
}
Your sections schema should be an Array.
const section = new schema.Entity('sections')
const sections = new schema.Array(section);
section.define({ sections });
const menu = new schema.Entity('menu', { sections });
Then, in using it...
const data = {
id: 123,
sections: [{
id: 1,
sections:[{ id: 4, sections: [ { id: 5, sections: [] } ] }]
}, {
id: 2,
sections:[]
}, {
id: 3,
sections:[]
}]
};
normalize(data, menu)
Will return:
{
"entities": {
"sections": {
"1": { "id": 1, "sections": [ 4 ] },
"2": { "id": 2, "sections": [] },
"3": { "id": 3, "sections": [] },
"4": { "id": 4, "sections": [ 5 ] },
"5": { "id": 5, "sections": [] }
},
"menu": {
"123": { "id": 123, "sections": [ 1, 2, 3 ] }
}
},
"result": 123
}
If someone has the case of nested objects of same "type", for example "sections" and top level structure is array of "sections" too, like this:
const data = [
{
id: 1,
sections:[{ id: 4, sections: [ { id: 5, sections: [] } ] }]
},
{
id: 2,
sections:[]
},
{
id: 3,
sections:[]
}
]
here one way to "unnest" them:
import {schema, normalize} from "normalizr";
const child = new schema.Entity("sections");
const sections = new schema.Array(child);
child.define({sections});
const topLevel = new schema.Entity("sections", {
sections
});
const customSchema = [topLevel];
console.log(normalize(data, customSchema));
What you will get is:
{
"entities":{
"sections":{
"1":{
"id":1,
"sections":[
4
]
},
"2":{
"id":2,
"sections":[
]
},
"3":{
"id":3,
"sections":[
]
},
"4":{
"id":4,
"sections":[
5
]
},
"5":{
"id":5,
"sections":[
]
}
}
},
"result":[
1,
2,
3
]
}

Categories

Resources