I have array of object like below:
pages= [
{
"id":1,
"name":"name1",
"languages":[
{
"id":1,
"lang":"en"
},
{
"id":2,
"lang":"de"
}
]
},
{
"id":2,
"name":"name2",
"languages":[
{
"id":1,
"lang":"en"
},
{
"id":2,
"lang":"de"
}
]
},
{
"id":3,
"name":"name3",
"languages":[
{
"id":1,
"lang":"en"
}
]
}
]
And array of languages(these will be set by clicking on checkboxes) is as below:
selectedLanguages=['en'];
Now, I want to filter the main array depending upon the selectedLanguages values. I have tried with below code:
pages.filter(page => {
var present = false;
page.languages.map(l => {
if(selectedLanguages.includes(l.lang)) {
present = true;
}
});
if(present) {
return page;
}
})
Desired output: if selectedLanguages = ['en'] then all items from pages, if de then first 2 elements.
It works but I am curious if I can make it better?
Any suggestions would be helpful :) Thanks.
You can use a combination of Array#Filter, Array#find and Array#includes for that :
let pages= [
{
"id":1,
"name":"name1",
"languages":[
{
"id":1,
"lang":"en"
},
{
"id":2,
"lang":"de"
}
]
},
{
"id":2,
"name":"name2",
"languages":[
{
"id":1,
"lang":"en"
},
{
"id":2,
"lang":"fr"
}
]
}
]
let selectedLanguages=['fr'];
let result = pages.filter(e => e.languages.find(l => selectedLanguages.includes(l.lang)));
console.log(result);
Rather than trying to create an intermediate array with .map, it would be better to simply check if some of the languages include a lang matching the selectedLanguages:
const pages=[{"id":1,"name":"name1","languages":[{"id":1,"lang":"en"},{"id":2,"lang":"de"}]},{"id":2,"name":"name2","languages":[{"id":1,"lang":"en"},{"id":2,"lang":"de"}]}]
const selectedLanguages=['en'];
console.log(
pages.filter(({ languages }) => (
languages.some(({ lang }) => selectedLanguages.includes(lang))
))
)
You can use filter() with indexOf() check for the selectedLanguages array:
var pages= [
{
"id":1,
"name":"name1",
"languages":[
{
"id":1,
"lang":"en"
},
{
"id":2,
"lang":"de"
}
]
},
{
"id":2,
"name":"name2",
"languages":[
{
"id":1,
"lang":"en"
},
{
"id":2,
"lang":"de"
}
]
},
{
"id":3,
"name":"name3",
"languages":[
{
"id":5,
"lang":"us"
},
{
"id":6,
"lang":"de"
}
]
}
];
var selectedLanguages=['en'];
var res = pages.filter((page) => {
var languageFound = page.languages.find(language => selectedLanguages.indexOf(language.lang) !== -1);
if(languageFound){
return page;
}
});
console.log(res);
Related
I am trying to filter unique object from the places Array inside the list Array, but not able to get the exact solution to find the unique place name, please find the array data below=>
"list":[
{
"id":1,
"uID": 1
"places":[
{
"name":"USA"
},
{
"name":"USA"
},
{
"name":"GER"
}
]
},
{
"id":2,
"uID":2
"places":[
{
"name":"USA"
},
{
"name":"GER"
},
{
"name":"GER"
}
]
}
]
The Expected output should be like this =>
"list":[
{
"id":1,
"uID": 1
"places":[
{
"name":"USA"
},
{
"name":"GER"
}
]
},
{
"id":2,
"uID":2
"places":[
{
"name":"USA"
},
{
"name":"GER"
}
]
}
]
Appreciate your help.
You can use Array.map() to map to map each member of the list to a new value.
For each value, we can remove duplicate places using a Set object.
We instantiate the Set using an array of the place names, using .map() again. The Set will then contain a list of the unique place names.
We then assign this to the places property of each output item.
const list = [ { "id":1, "uID": 1, "places":[ { "name":"USA" }, { "name":"USA" }, { "name":"GER" } ] }, { "id":2, "uID":2, "places":[ { "name":"USA" }, { "name":"GER" }, { "name":"GER" } ] } ]
const result = list.map(({ places, ...obj }) => {
const uniquePlaces = new Set(places.map(item => item.name));
return { ...obj, places: [ ...uniquePlaces].map(name => ({ name })) }
})
console.log('Result:', result);
.as-console-wrapper { max-height: 100% !important; }
You can use Set() to filter duplicate by using add() method.
for more reference take a look at this link : https://levelup.gitconnected.com/how-to-find-unique-values-by-property-in-an-array-of-objects-in-javascript-50ca23db8ccc
Convert the object(s) in places array as (JSON) string via JSON.stringify().
With new Set() to distinct the JSON string.
Convert to array from result 2 via Array.from().
Convert each (JSON) string in the array (from 3) to the object via JSON.parse().
list = list.map(x => {
x.places = Array.from([...new Set(x.places.map(x => JSON.stringify(x)))])
.map(x => JSON.parse(x));
return x;
})
Sample Typescript Playground
const foo = {
"list":[
{
"id":1,
"uID": 1,
"places":[
{
"name":"USA"
},
{
"name":"USA"
},
{
"name":"GER"
}
]
},
{
"id":2,
"uID":2,
"places":[
{
"name":"USA"
},
{
"name":"GER"
},
{
"name":"GER"
}
]
}
]};
const newList = foo.list.map(element => {
let filteredPlaces = [];
element.places.forEach(place => {
const checkExistingPlaces = filteredPlaces.some(elem => elem.name === place.name);
if (!checkExistingPlaces) {
filteredPlaces.push(place);
}
});
element.places = filteredPlaces;
return element;
});
console.log(newList)
i have an array of objects of the below format
each with a unique 'sub-task' entry, each of this sub-task is to be embedded as a children element of each unique 'task' from the 'tasks' array
[
{
"sub-task":"abc",
"task":"alpha1"},
{
"sub-task":"def",
"task":"alpha1"},
{
"sub-task":"ijkl",
"task":"proto"},
{
"sub-task":"mno",
"task":"def"},
{
"sub-task":"qrs",
"task":"proto"},
{
"sub-task":"asdf",
"task":"mno"},
]
i was trying to frame an another array of below format
[
{
"name":"alpha1",
"children":[
{
"name":"abc"
},
{
"name":"def",
"children":[
{
"name":"mno"
}
]
}
]
},
{
"name":"proto",
"children":[
{
"name":"ijkl"
},
{
"name":"qrs",
"children":[
{
"name":"asdf"
}
]
}
]
}
]
i was trying of below logic, but ended up with no solution...
var treeData = [];
for( var ele of tasks){
recurOn(treeData,ele);
}
function recurOn(arr,obj){
if(arr.length == 0){
treeData.push({name:obj.parentGroup,children:[{name:obj.groupName}]})
//console.log(treeData);
return 1;
}else {
for(var item of treeData){
if(item.name == obj.parentGroup){
//console.log('item: ', item);
item.children.push({name:obj.groupName});
break;
}
else {
treeData.push(recurOn([],obj))
}
}
return 1;
}
}
//console.log(treeData);
//console.log(result);
Since the no of levels an elements holds is not known i was unable to fix for a logic
Use a map to store object reference.
let input = [
{ "sub-task": "abc", "task": "alpha1" },
{ "sub-task": "def", "task": "alpha1" },
{ "sub-task": "ijkl", "task": "proto" },
{ "sub-task": "mno", "task": "def" },
{ "sub-task": "qrs", "task": "proto" },
{ "sub-task": "asdf", "task": "mno" },
];
let map = new Map, result = [];
input.forEach(({ ["sub-task"]: name, task }) => {
let node = map.get(task), child = { name, children: [] };
if (!node) {
map.set(task, node = { name: task, children: [] });
result.push(node);
}
map.set(name, child);
node.children.push(child);
})
console.log(result);
I have a nested json array as below:
[
{
"filename":"Vegetable",
"children":[
{
"filename":"Juicy",
"children":[
{
"filename":"Tomato",
"type":"ts1"
},
{
"filename":"Carrot",
"type":"ts2"
},
,
{
"filename":"Onion",
"type":"ts3"
}
]
},
{
"filename":"Sweet",
"children":[
{
"filename":"Potato",
"type":"ts4"
},
{
"filename":"Water melon",
"type":"ts"
}
]
}
]
},
{ filename:"Fruits"..........
},....
]
I need to filter the array in such a way that below conditions:
Filename = Juicy given(it can be Sweet as well i mean i that level 2nd level of array)
Under that will have a filter text suppose it is 't'. Then it should match file names Tomato, Carrot since it contains t
Bases on conditions below the expected result is
[
{
"filename":"Vegetable",
"children":[
{
"filename":"Juicy",
"children":[
{
"filename":"Tomato",
"type":"ts1"
},
{
"filename":"Carrot",
"type":"ts2"
}
]
},
{
"filename":"Sweet",
"children":[
{
"filename":"Potato",
"type":"ts4"
},
{
"filename":"Water melon",
"type":"ts"
}
]
}
]
},
{ filename:"Fruits"..........
},....
]
ie it should eleminate
{ "filename":"Onion",
"type":"ts3"
}
Since onion don't contain 't'.
I have tried with filter, map using arrow functions but not working as expected.
I have tried function filterby =(childname, filterText).filter =>{...}
Please guide me...
I have come with one solution that uses two nested Array.map() and the Array.filter() at the last level of childrens:
const input = [
{
"filename":"Vegetable",
"children":[
{
"filename":"Juicy",
"children":[
{"filename":"Tomato", "type":"ts1"},
{"filename":"Carrot", "type":"ts2"},
{"filename":"Onion", "type":"ts3"}
]
},
{
"filename":"Sweet",
"children":[
{"filename":"Potato", "type":"ts4"},
{"filename":"Water melon", "type":"ts"}
]
}
]
},
{
"filename":"Fruits",
"children": []
}
];
const filterBy = (arr, childname, filterText) =>
{
return arr.map(({filename, children}) =>
{
return {filename, children: children.map(({filename, children}) =>
{
if (filename === childname)
return {filename, children: children.filter(
x => x.filename.match(filterText)
)};
else
return {filename, children};
})};
});
}
console.log(
"Filter the Juits by text 't': ",
filterBy(input, "Juicy", "t")
);
console.log(
"Filter the Sweet by text 'r': ",
filterBy(input, "Sweet", "r")
);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
I need to convert the the init array to final array preferably using lodash.
initArray = [
{
"date":"2017-08-15",
"data":[
{
"color":"orange",
"count":100
},
{
"color":"green",
"count":101
}
]
},
{
"date":"2017-08-14",
"data":[
{
"color":"orange",
"count":102
},
{
"color":"green",
"count":103
}
]
}
]
finalArray = [
{
"color":"orange",
"data":[
100,
102
]
},
{
"color":"green",
"data":[
101,
103
]
}
]
This way seems like the lodash calls make sense to me.
// var _ = require('lodash')
initArray = [
{
"date":"2017-08-15",
"data":[
{
"color":"orange",
"count":100
},
{
"color":"green",
"count":101
}
]
},
{
"date":"2017-08-14",
"data":[
{
"color":"orange",
"count":102
},
{
"color":"green",
"count":103
}
]
}
]
result = _(initArray)
//.map('data')
//.flatten()
.flatMap('data') // instead of .map('data').flatten()
.groupBy('color')
.map((item, key) => ({
color: key,
count: _.map(item, 'count')
}))
.value()
console.log(result)
<script src="https://cdn.jsdelivr.net/lodash/4/lodash.min.js"></script>
you can use reduce to flatten the original array, so that all data arrays are on same level. Then use _.transform to get a temp object mapping colors to array of their counts. and then you can push things to finalArray using forEach.
var initArray = [
{
"date":"2017-08-15",
"data":[
{
"color":"orange",
"count":100
},
{
"color":"green",
"count":101
}
]
},
{
"date":"2017-08-14",
"data":[
{
"color":"orange",
"count":102
},
{
"color":"green",
"count":103
}
]
}
];
var finalArray = [];
var temp = _.transform(initArray.reduce((a,b) => a.data.concat(b.data)),
(r, v) => (r[v.color] || (r[v.color] = [])).push(v.count), {});
_.forEach(temp, (v,k) => finalArray.push({color:k, count:v}));
console.log(finalArray);
<script src="https://cdn.jsdelivr.net/lodash/4/lodash.min.js"></script>
I'm a trying to access the change order information as seen below to create a list of all the change_order_names. Using the current code I am getting the results I have posted. Will someone show me how I can access the change order information and produce the list?
if (componentType == CHANGE_ORDER_TYPE) {
if (!this.props.data) {
return null;
} else {
const changeList = this.props.data.map(function (result) {
return (result.change_orders);
});
// return resultsList;
console.log(changeList);
}
}
This is the current response from the map method above.
[
[
{
"id":1,
"change_order_name":"change 1",
"project_id":"1",
"cws_change_order_id":"33214324",
"slug":"change-1",
"created_at":null,
"updated_at":null
},
{
"id":2,
"change_order_name":"change 2",
"project_id":"1",
"cws_change_order_id":"3211324",
"slug":"change-2",
"created_at":null,
"updated_at":null
}
],
[
{
"id":3,
"change_order_name":"change 3",
"project_id":"2",
"cws_change_order_id":"3234324",
"slug":"change-3",
"created_at":null,
"updated_at":null
},
{
"id":4,
"change_order_name":"change 4",
"project_id":"2",
"cws_change_order_id":"6234532",
"slug":"change-4",
"created_at":null,
"updated_at":null
}
],
[
{
"id":5,
"change_order_name":"change 5",
"project_id":"3",
"cws_change_order_id":"3124214",
"slug":"change-5",
"created_at":null,
"updated_at":null
}
]
]
This is how I dug down to get get access to the individual change_orders
if (componentType == CHANGE_ORDER_TYPE) {
if (!this.props.data) {
return null;
} else {
const changeList = this.props.data.map(function (result) {
return (result.change_orders);
});
let changeOrdersArr = [];
for (let i = 0; i < changeList.length; i++) {
let inner = changeList[i];
for (let z = 0; z < inner.length; z++) {
changeOrdersArr.push(inner[z])
}
}
It's not entirely clear what your desired output is, but I think you want a single array with all change_orders in it? If this is correct then you can use the reduce function after your current map function:
if (componentType == CHANGE_ORDER_TYPE) {
if (!this.props.data) {
return null;
} else {
const changeList = this.props.data.map(function (result) {
return (result.change_orders);
}).reduce((output, item) => [...output, ...item], []);
// return changeList;
console.log(changeList);
}
}
const mapOutput = [
[
{
"id":1,
"change_order_name":"change 1",
"project_id":"1",
"cws_change_order_id":"33214324",
"slug":"change-1",
"created_at":null,
"updated_at":null
},
{
"id":2,
"change_order_name":"change 2",
"project_id":"1",
"cws_change_order_id":"3211324",
"slug":"change-2",
"created_at":null,
"updated_at":null
}
],
[
{
"id":3,
"change_order_name":"change 3",
"project_id":"2",
"cws_change_order_id":"3234324",
"slug":"change-3",
"created_at":null,
"updated_at":null
},
{
"id":4,
"change_order_name":"change 4",
"project_id":"2",
"cws_change_order_id":"6234532",
"slug":"change-4",
"created_at":null,
"updated_at":null
}
],
[
{
"id":5,
"change_order_name":"change 5",
"project_id":"3",
"cws_change_order_id":"3124214",
"slug":"change-5",
"created_at":null,
"updated_at":null
}
]
];
const change_orders = mapOutput.reduce((orders, arr) => [...orders,...arr],[]);
console.log(change_orders);