I have the following:
{
"SOL": {
"B": [
"ABC",
"DEF"
],
"C": [
"JKL",
"MNO"
]
}
}
I'd like it to read:
{
"SOL": [
{
"id": "B",
"states": [
{
"id": "ABC"
},
{
"id": "DEF"
]
},
{
"id": "C",
"states": [
{
"id": "JKL"
},
{
"id": "MNO"
}
]
}
]
}
I've managed to give an "id" key to the 2nd level but I can't figure out how to add one to each of the states - how can I do that?
Code:
object.SOL = Object.keys(object.SOL).map(function (k) {
return { id: k, states: object.SOL[k] };
})
Here's a fiddle
You can just use another map inside to remap the states to objects:
object.SOL = Object.keys(object.SOL).map(function (k) {
return {
id: k,
states: object.SOL[k].map(function(i){
return {id: i };
})
}
});
Updated fiddle: https://jsfiddle.net/ouybL99u/2/
object.SOL = Object.keys(object.SOL).map(function (k) {
return { id: k, states: object.SOL[k].map(function(kk){ return {id:kk} }) };
})
Related
I want to remove duplicates within the map function and I have looked through the different posts on the internet but I am still not finding the solution.
The JSON:
"results": [
{
"data": {
"labels": {
"results": [
{
"name": "tom"
}
]
}
}
},
{
"data": {
"labels": {
"results": [
{
"name": "jerry"
}
]
}
}
},
{
"data": {
"labels": {
"results": [
{
"name": "tom"
}
]
}
}
}
]
The code:
obj.results.map((items) => {
if (items.data.labels.results.length) {
items.data.labels.results.map((result) => {
console.log(result.name);
});
}
});
Result
tom
jerry
tom
Expected Result
tom
jerry
Tried this solution but didn't work
obj.results.map((items) => {
if (items.data.label.results.length) {
items.data.label.results.map((result) => {
console.log(Array.from(new Set(result.name)));
});
}
});
Result from above code
[ 't', 'o', 'm' ]
[ 'j', 'e', 'r', 'r', 'y' ]
[ 't', 'o', 'm' ]
I would use reduce since it is perfect for iterating an array with an accumulative value. In this case, an object.
const x = [{
"data": {
"results": [{
"name": "tom"
}]
}
},
{
"data": {
"results": [{
"name": "jerry"
}]
}
},
{
"data": {
"results": [{
"name": "tom"
}]
}
}
]
var result = Object.values(x.reduce(function(acc, item) {
var name = item.data.results[0].name
// acc[name] = item;
acc[name] = name;
return acc;
}, {}))
console.log(result)
you can achieve this using flatMap to get all name objects and then map to extract the name field. After that a Set to dedupe. [...new Set(..)] converts the Set back to an array
const results = [{
"data": {
"labels": {
"results": [{
"name": "tom"
}, {
"name": "another name"
}]
}
}
}, {
"data": {
"labels": {
"results": [{
"name": "jerry"
}]
}
}
}, {
"data": {
"labels": {
"results": [{
"name": "tom"
}]
}
}
}]
const res = [...new Set(results.flatMap(({data:{labels: {results}}}) => results).map(({name}) => name))]
//alternative
//const res = [...new Set(results.map(({data:{labels: {results}}}) => results).flat().map(({name}) => name))]
console.log(res)
Javascript
I have a nested array of objects, I'm trying to filter the given array of objects using a property from the third level of its array property value. For example, from the below array I like to filter the entire array using the property ListId: 10
Example
let test = {
"test":true,
"group":[
{
"name":"header",
"value":[
{
"id":"0",
"list":[
{
"ListId":10,
"name":"string1",
"state":"BY",
"techId":0
},
{
"ListId":11,
"name":"string2",
"state":"BY"
},
{
"ListId":12,
"name":"string3",
"state":"BY"
}
]
}
]
},
{
"name":"header2",
"value":[
{
"id":"01",
"list":[
{
"ListId":100,
"name":"string1",
"state":"BY",
"techId":0
},
{
"ListId":111,
"name":"string2",
"state":"BY"
},
{
"ListId":121,
"name":"string3",
"state":"BY"
}
]
}
]
}
]
}
Filtervalue with ListId = 10
Expected output :
{
"test":true,
"group":[
{
"name":"header",
"value":[
{
"id":"0",
"list":[
{
"ListId":10,
"name":"string1",
"state":"BY",
"techId":0
}
]
}
]
}
]
}
How can I use the filter method using javascript to get this expected result?
You can two it in two times :
First, filter the list arrays,
Secondly filter the groups array using the some method
let test= {
"test": true,
"group": [
{
"name": "header",
"value": [
{
"id": "0",
"list": [
{
"ListId": 10,
"name": "string1",
"state": "BY",
"techId": 0
},
{
"ListId": 11,
"name": "string2",
"state": "BY"
},
{
"ListId": 12,
"name": "string3",
"state": "BY"
}
]
}
]
},
{
"name": "header2",
"value": [
{
"id": "01",
"list": [
{
"ListId": 100,
"name": "string1",
"state": "BY",
"techId": 0
},
{
"ListId": 111,
"name": "string2",
"state": "BY"
},
{
"ListId": 121,
"name": "string3",
"state": "BY"
}
]
}
]
}
]
}
test.group.forEach(group => {
group.value.forEach(value => {
value.list = value.list.filter(list => list.ListId === 10)
})
})
test.group = test.group.filter(group => group.value.some(value => value.list.length > 0))
console.log(test)
Note : You should use plural names for you arrays, it helps understanding the data. For example lists not list for the array.
let z ={"group1": [
{
"name": "header",
"value": [
{
"id": 0,
"list": [
{
"ListId": 10,
"Name": "string1"
},
{
"ListId": 11,
"Name": "string2"
}
]
}
]
}
]}
// This function was written from understading that 'group1' is not a fixed property, but part of a dynamic list due to the number '1'
const getItemByListId = (list, listId) => {
const listKeys = Object.keys(list);
const selectedListKey = listKeys.find(key => {
const groupItems = list[key];
const selectedItem = groupItems.find(({ value: nestedItems }) => {
const selectedNestedItem = nestedItems.find(({ list }) => {
const selectedList = list.find(({ ListId }) => ListId === listId)
return selectedList;
});
return selectedNestedItem;
});
return selectedItem;
});
if (!selectedListKey) {
return null;
}
return list[selectedListKey];
};
console.log(getItemByListId(z, 10));
I am having a dynamic JSON array in below format,
let main_data = [
{
"client":[
{
"name":"aaaa",
"count":"1",
"filter":{
"type":{
"name":"test3"
}
}
},
{
"name":"bbbb",
"count":"9",
"filter":{
"type":{
"name":"test2"
}
}
}
]
},
{
"compute":[
{
"name":"cccc",
"count":"6",
"filter":{
"type":{
"name":"test"
}
}
}
]
}
]
Here key "name" is unique. When updating a form, I will get an json array like below,
let new_data = [
{
"client":[
{
"name":"bbbb",
"count":"1234",
"type":{
"name":"updated_name"
}
}
}
]
}
]
I need to check the "name" in the json array in "main_data" and remove the existing one and update with the new "updated_data" into the "main_data". (no Jquery please)
Expected output,
let main_data = [
{
"client":[
{
"name":"aaaa",
"count":"1",
"filter":{
"type":{
"name":"test3"
}
}
},
{
"name":"bbbb",
"count":"123",
"filter":{
"type":{
"name":"updated_name"
}
}
}
]
},
{
"compute":[
{
"name":"cccc",
"count":"6",
"filter":{
"type":{
"name":"test"
}
}
}
]
}
]
Is there any way to achive this. Any help would be much appreciated. Thanks in advance.
Try this
let main_data = [{
client: [{
name: "aaaa",
count: "1",
filter: {
type: {
name: "test3"
}
}
},
{
name: "bbbb",
count: "9",
filter: {
type: {
name: "test2"
}
}
}
]
},
{
compute: [{
name: "cccc",
count: "6",
filter: {
type: {
name: "test"
}
}
}]
}
];
let new_data = [{
client: [{
name: "bbbb",
count: "1234",
filter: {
type: {
name: "updated_name"
}
}
}]
}];
const res = main_data.map((item, index) => {
if (item.client) {
const clients = item.client.map(client => {
if (client.name === new_data[0].client[0].name) {
client = new_data[0].client[0];
}
return client;
});
return {
client: clients
};
}
return item;
});
console.log(res);
There may very well be a fancy way to get this done but one can always just find the matching item and replace it. eg.
let main_data = [
{
"client": [
{
"name": "aaaa",
"count": "1",
"filter": {
"type": {
"name": "test3"
}
}
},
{
"name": "bbbb",
"count": "123",
"filter": {
"type": {
"name": "updated_name"
}
}
}
]
},
{
"compute": [
{
"name": "cccc",
"count": "6",
"filter": {
"type": {
"name": "test"
}
}
}
]
}
];
let new_data = [
{
"client": [
{
"name": "bbbb",
"count": "1234",
"type": {
"name": "updated_name"
}
}
]
}
];
console.log("before:" + JSON.stringify(main_data));
newItem = new_data[0]["client"][0];
mainDataList = main_data[0]["client"];
for (i = 0; i < mainDataList.length; i++) {
if (mainDataList[i].name == newItem.name) {
mainDataList[i] = newItem;
}
}
console.log("after:" + JSON.stringify(main_data));
will output
before:[{"client":[{"name":"aaaa","count":"1","filter":{"type":{"name":"test3"}}},{"name":"bbbb","count":"123","filter":{"type":{"name":"updated_name"}}}]},{"compute":[{"name":"cccc","count":"6","filter":{"type":{"name":"test"}}}]}]
after:[{"client":[{"name":"aaaa","count":"1","filter":{"type":{"name":"test3"}}},{"name":"bbbb","count":"1234","type":{"name":"updated_name"}}]},{"compute":[{"name":"cccc","count":"6","filter":{"type":{"name":"test"}}}]}]
Here's a simple way to do this, let's say your new data is at variable newData:
main_data.client.filter(item => item.name === newData.name).push(newData)
I have a json array and I want to sort the array based on its index number
[
{
"name":"abc",
"index":2,
"values":[
{
"work":"three3",
"index":3
},
{
"work":"one1",
"index":1
},
{
"work":"two2",
"index":2
}
]
},
{
"name":"pqr",
"index":1,
"values":[
{
"work":"three",
"index":3
},
{
"work":"two",
"index":2
},
{
"work":"one",
"index":1
}
]
}
]
What I expect from this array is:
[
{
"filename":"pqr",
"children":[
{
"work":"one",
"index":1
},
{
"work":"two",
"index":2
},
{
"work":"three",
"index":3
}
]
},
{
"filename":"abc",
"children":[
{
"work":"one1",
"index":1
},
{
"work":"two2",
"index":2
},
{
"work":"three3",
"index":3
}
]
}
]
Tried something like below.
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};
})};
});
}
It is a json array and what we can not be sure it will be in order so I want an array or object should be in sorted order
But how can I include that index in inner level and outer level and sort using it accordingly?
You can first sort the array based on index. This will return a sorted array now use map. Inside the callback function get the values array and again sort it.Inside the array map function return the object with required key and value
let data = [{
"name": "abc",
"index": 2,
"values": [{
"work": "three3",
"index": 3
},
{
"work": "one1",
"index": 1
},
{
"work": "two2",
"index": 2
}
]
},
{
"name": "pqr",
"index": 1,
"values": [{
"work": "three",
"index": 3
},
{
"work": "two",
"index": 2
},
{
"work": "one",
"index": 1
}
]
}
]
let newdt = data.sort(function(a, b) {
return a.index - b.index
}).map(function(item) {
let val = item.values.sort(function(a, b) {
return a.index - b.index;
})
return {
name: item.name,
children: val
}
})
console.log(newdt)
First sort the outer array, use same function to sort inner array
function compare(a, b) {
if (a.index < b.index)
return -1;
if (a.index > b.index)
return 1;
return 0;
}
var objs = [{
"name": "abc",
"index": 2,
"values": [{
"work": "three3",
"index": 3
},
{
"work": "one1",
"index": 1
},
{
"work": "two2",
"index": 2
}
]
},
{
"name": "pqr",
"index": 1,
"values": [{
"work": "three",
"index": 3
},
{
"work": "two",
"index": 2
},
{
"work": "one",
"index": 1
}
]
}
]
var result = objs.sort(compare).map(function(item) {
var children = item.values.sort(compare);
return {
filename: item.name,
children: children
}
});
console.log(result);
I have an array of object, and i want to convert it into a map of key value pairs with the id as the key. However, I want to do it for both the root level and within the recipes attribute.
Array resp:
[
{
"id": "1",
"recipes": [
{
"id": 4036
},
{
"id": 4041
}
]
},
{
"id": "2",
"recipes": [
{
"id": 4052
},
{
"id": 4053
}
]
}
]
I came across _.keyBy() which maps an attribute as the key, but it doesn't allow nested levels.
Function:
var respObj = _.keyBy(resp, 'id');
Is there an elegant solution to massage resp to make all the objects nested within the array use id as key?
thanks!
you can do it with _.keyBy and _.mapValues
_.chain(resp)
.keyBy('id')
.mapValues(function(item) {
item.recipes = _.keyBy(item.recipes, 'id');
return item;
})
.value();
This is a generic solution that runs _.keyBy recursively on arrays, and the objects inside them:
function deepKeyBy(arr, key) {
return _(arr)
.map(function(o) { // map each object in the array
return _.mapValues(o, function(v) { // map the properties of the object
return _.isArray(v) ? deepKeyBy(v, key) : v; // if the property value is an array, run deepKeyBy() on it
});
})
.keyBy(key); // index the object by the key
}
I've added another level of data in the example (ingredients):
function deepKeyBy(arr, key) {
return _(arr)
.map(function(o) {
return _.mapValues(o, function(v) {
return _.isArray(v) ? deepKeyBy(v, key) : v;
});
})
.keyBy(key);
}
var arr = [{
"id": "1",
"recipes": [{
"id": 4036,
"ingerdients": [{
"id": 5555555
}, {
"id": 5555556
}, {
"id": 5555557
}]
}, {
"id": 4041
}]
}, {
"id": "2",
"recipes": [{
"id": 4052
}, {
"id": 4053
}]
}];
var result = deepKeyBy(arr, 'id');
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.min.js"></script>
You could get a flattened collection of recipes, concatenate the response and then key by id:
var result = _.chain(resp)
.flatMap('recipes')
.concat(resp)
.keyBy('id')
.value()
The flatMap call will pluck all the recipes from the response and flatten the arrays so we're left with this:
[
{ "id": 4036 },
{ "id": 4041 },
{ "id": 4052 },
{ "id": 4053 }
]
The response is then appended to this array using concat so we then have:
[
{ "id": 4036 },
{ "id": 4041 },
{ "id": 4052 },
{ "id": 4053 },
{ "id": "1", recipes: ... },
{ "id": "2", recipes: ... }
]
Finally we use keyBy to get the required structure .
var resp = [
{
"id": "1",
"recipes": [
{
"id": 4036
},
{
"id": 4041
}
]
},
{
"id": "2",
"recipes": [
{
"id": 4052
},
{
"id": 4053
}
]
}
]
var result = _.chain(resp)
.flatMap('recipes')
.concat(resp)
.keyBy('id')
.value()
document.getElementById('result').textContent = JSON.stringify(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>
<p>
<pre id="result"></pre>
</p>