I have the following object with arrays:
{
"brands": [
"accessible-icon",
"accusoft",
"adn",
"adobe",
"adversal",
],
"regular": [
"address-book",
"address-card",
"angry",
"bell",
],
"solid": [
"ad",
"address-book",
"address-card",
"adjust",
"air-freshener",
"align-center",
]
}
I have a function which returns one item from one of the array groups. I have to find out which array group the item was pulled from. From what I understood, it's not possible to look up parent keys in js?
Getting the parent key would be ideal, otherwise, is it possible to add the parent key to all the nested items? For example the nested items in the brands array would become:
"brands": [
"brands-accessible-icon",
"brands-accusoft",
"brands-adn",
"brands-adobe",
"brands-adversal",
],
Then I can use regex to extract brands.
More info:
Initially I'm transforming objects into object with array groups. Here is an example of one of the objects named brands:
{
"faAccessibleIcon": {
"prefix": "fab",
"iconName": "accessible-icon",
"icon": [
448,
512,
[],
"f368",
]
},
"faAccusoft": {
"prefix": "fab",
"iconName": "accusoft",
"icon": [
640,
512,
[],
"f369",
]
},
"faAcquisitionsIncorporated": {
"prefix": "fab",
"iconName": "acquisitions-incorporated",
"icon": [
344,
512,
[],
"f6af",
]
},
}
Then I simplify the objects:
const array = {
"brands": Object.keys(brands).map(e=> brands[e].iconName),
"regular": Object.keys(regular).map(e=> regular[e].iconName),
"solid": Object.keys(solid).map(e=> solid[e].iconName),
};
And array becomes the object with arrays seen at the top of my question. The array structure must remain like that. Is there a way to combine prefix and iconName and get brands-accessible-icon, brands-accusoft, etc, in the nested array items, for each group of arrays?
You could get the keys of the object and find the value in the array.
const getKey = (object, value) => Object.keys(object).find(k => object[k].includes(value));
var data = { brands: ["accessible-icon", "accusoft", "adn", "adobe", "adversal"], regular: ["address-book", "address-card", "angry", "bell"], solid: ["ad", "address-book", "address-card", "adjust", "air-freshener", "align-center"] };
console.log(getKey(data, "bell"));
I think there is an easy answer to it.
const array = {
"brands": Object.keys(brands).map(e=> "brands-"+brands[e].iconName),
"regular": Object.keys(regular).map(e=> "regular-"+regular[e].iconName),
"solid": Object.keys(solid).map(e=> "solid-"+solid[e].iconName),
};
Here you go.
By getting the entries of your objects and then mapping every object to add their parent's name into their string, you can create your desired output.
(Unless I misunderstood your question since every answer seems to do something different)
Working example :
const data = {
"brands": [
"accessible-icon",
"accusoft",
"adn",
"adobe",
"adversal",
],
"regular": [
"address-book",
"address-card",
"angry",
"bell",
],
"solid": [
"ad",
"address-book",
"address-card",
"adjust",
"air-freshener",
"align-center",
]
}
const result = Object.entries(data).reduce((acc, [key, value]) => ({ ...acc, [key]: value.map(obj => key + '-' + obj) }), {})
console.log(result)
Related
I'm attempting to search each of the objects listed below from my dataset to see if they contain a value and if they do have that value to add the entire object into a new array.
Example:
Search List of Objects for Data "Continuous", if that data exists (Which it does in Doormerica and Hager) then take the entire object "Doormerica" and "Hager" and put the entire thing into a new array.
{
"Doormerica": {
"Floor Stops": [],
"Overhead Stop": [],
"Pull": [],
"Chain Stop": [],
"Continuous": [
"ALX",
"AL",
"QR"
],
"Kick": [],
"Back to Back Pull": [],
"Concealed": [],
"Butt": [],
"Surface Mount": [],
"Mop": [],
"Armor": [],
"Push": [],
"Wall Stops": []
},
"Schlage": {
"Mortise": [],
"Cylindrical": [
"ALX",
"AL",
"QR"
],
"Deadbolt": [],
"Dummy": [],
"Interconnected": [],
"Cylinders": []
},
"Pemko": {
"Sweeps": [
"345AV"
],
"Permiter Seal": [
"303AS"
],
"Thresholds": [
"170A"
],
"Rain Drip": [
"346C"
],
"Astragal": []
},
"LCN": {
"Surface Mount": [
"4040XP"
],
"Concealed": []
},
"Hager": {
"Butt": [],
"Continuous": []
}
}
Data Transformation
I decided to post this solution because the question asks how to "take the entire object". And including the name (Doormerica, Hager, etc.) in the result, either as a key or a value, seems an important part of the transformation. And we can accomplish this in one pass using Object.entries(), Array.reduce(), Spread Syntax, and the appropriate transformation code.
Examples of both transformations
[{"Doormerica": { "Floor Stops": [], ...}] // name as a key
[{ "Name": "Doormerica", "Floor Stops": [], ...}] // name as a value
Snippet
The snippet shows the complete code for doing both transformations.
const data = {Doormerica:{"Floor Stops":[],"Overhead Stop":[],Pull:[],"Chain Stop":[],Continuous:["ALX","AL","QR"],Kick:[],"Back to Back Pull":[],Concealed:[],Butt:[],"Surface Mount":[],Mop:[],Armor:[],Push:[],"Wall Stops":[]},Schlage:{Mortise:[],Cylindrical:["ALX","AL","QR"],Deadbolt:[],Dummy:[],Interconnected:[],Cylinders:[]},Pemko:{Sweeps:["345AV"],"Permiter Seal":["303AS"],Thresholds:["170A"],"Rain Drip":["346C"],Astragal:[]},LCN:{"Surface Mount":["4040XP"],Concealed:[]},Hager:{Butt:[],Continuous:[]}};
let subset = Object.entries(data).reduce((a,v) =>
v[1].hasOwnProperty("Continuous") ? [...a, {[v[0]]: v[1]} ] : a
// alternative methods adds a name property
// v[1].hasOwnProperty("Continuous") ? [...a, {Name: v[0], ...v[1]} ] : a
, []);
console.log(subset);
So we loop over the values of the object, search for our "term" on each of those values = objects. To search object for property you only need to check if obj[property] exists.
var obj = {Doormerica:{"Floor Stops":[],"Overhead Stop":[],Pull:[],"Chain Stop":[],Continuous:["ALX","AL","QR"],Kick:[],"Back to Back Pull":[],Concealed:[],Butt:[],"Surface Mount":[],Mop:[],Armor:[],Push:[],"Wall Stops":[]},Schlage:{Mortise:[],Cylindrical:["ALX","AL","QR"],Deadbolt:[],Dummy:[],Interconnected:[],Cylinders:[]},Pemko:{Sweeps:["345AV"],"Permiter Seal":["303AS"],Thresholds:["170A"],"Rain Drip":["346C"],Astragal:[]},LCN:{"Surface Mount":["4040XP"],Concealed:[]},Hager:{Butt:[],Continuous:[]}};
function my_search(obj, term) {
return Object.values(obj).reduce(function(agg, value) {
if (value[term]) {
agg.push(value)
}
return agg;
}, [])
}
console.log(my_search(obj, "Continuous"))
.as-console-wrapper {max-height: 100% !important}
I have an array like this.
let Array = [{
id: 1,
name: "Car",
cars: [{
id: 2,
name: "Hyundai",
models: [
"Verna", "Aura", "Azera", "Accent", "Sonata"
]
}]
}....]
And I think this not the best way: Array.map(car => car.cars.map(model => model.models)).
Is there any other way?
There is no 'short way' as what you are doing is very specific to your problem. The way you wrote it is the most concise if you want to end up with an array like:
let Array = [
[
[ "Verna", "Aura", "Azera", "Accent", "Sonata" ],
[ ... ],
],
[ ... ],
]
But if you want to flatten the array, you can consider writing it as:
Array
.map(car => car.cars).flat()
.map(model => model.models).flat()
This will result in an array like this:
[ "Verna", "Aura", "Azera", "Accent", "Sonata", ... ]
Notes
Do not call an array Array as is the name of the array constructor. You will lose the ability to do new Array().
I have an array like this:
[
{
"id": 10002,
"flag": false,
"list": [
"aaa",
"bbb"
]
},
{
"id": 10001,
"flag": true,
"list": [
"10002",
"10003"
]
},
{
"id": 10003,
"flag": false,
"list": [
"ccc",
"ddd"
]
}
]
i tried this
initially i have "10001" value so iterate this array to take "list" array if flag==true then stored into newarray. but its not working.
I want it to be like this: [ "aaa", "bbb", "ccc", "ddd" ].
If i understand correctly this is what you want:
const someArray = [
{
"id": 10001,
"list": [
"10002",
"10003"
]
},
{
"id": 10002,
"list": [
"aaa",
"bbb"
]
},
{
"id": 10003,
"list": [
"ccc",
"ddd"
]
}
];
const [head,...rest] = someArray;
const result = head.list.reduce((acc,currentId)=>acc.concat(rest.find(({id})=> id === parseInt(currentId)).list),[]);
Here is a jsFiddle https://jsfiddle.net/sudakatux/9hju85mt/22/
Explanation:
take the head and splitted from the rest since the head contains the ids.
using the head as a dictionary find each list for each id in the head and concatenate
note the id must be in the subsequent list else it will fail with undefined. if you want to account for this error you can set a defualt empty object with a list. for example this part:
rest.find(({id})=> id === parseInt(currentId)).list
Will look like
rest.find(({id})=> id === parseInt(currentId)) || {list:[]}).list
Which basically means if its undefined return an object that has an empty list so then it will concatenate an empty list which results in being the same list. (like multiplying by 1 in a multiplication)
Hope it helps.
EDIT after your edit.
If your array is in different order you need to find the dictonary and then the logic is the same
const [newHead] = otherArray.filter(({list}) => list.every(elem=>!isNaN(elem)));
const result2 = newHead.list.reduce(
(acc,currentId) =>acc.concat(otherArray.find(({id})=> id === parseInt(currentId)).list),[]);
if you are testing for the flag then your head filter would look like. the blocks are the same the only thing that changes is the condition.
const [newHead] = otherArray.filter(({flag}) => flag));
(note* that instead of using the rest i used the complete array(otherArray). since im targeting equality.
Im using filter and extracting the first element of the result. because im accounting for the possibility that in the future you may have more than one "dictionary element". if thats the case in the future then you just have to concat the lists from the filter result
const array = [
{
id: 10001,
flag: true,
list: ["10002", "10003"]
},
{
flag: false,
id: 10002,
list: ["aaa", "bbb"]
},
{
flag: false,
id: 10003,
list: ["ccc", "ddd"]
}
];
const isHead = item => item.flag && item.id === 10001;
const head = array.find(isHead);
const rest = array.filter(item => !isHead(item));
const result = rest
.flatMap(item =>
head.list.includes(item.id.toString()) && item.list
);
console.log(result);
You can map over the list of the first item and concat all the lists from those ids.
const mapItems = (input) => {
const source = input[0].list;
source.reduce((results, id) => {
return results.concat(input.find(item => item.id === id).list);
}, []);
};
mapItems([
{
"id": 10001,
"list": [
"10002",
"10003"
]
},
{
"id": 10002,
"list": [
"aaa",
"bbb"
]
},
{
"id": 10003,
"list": [
"ccc",
"ddd"
]
}
]);
You can fetch the values of the list of first object in the array as arr[0]['list']
Once you have these values (10002,10003) then you can fetch the list values of remaining objects in the array whose id key matches one of the above values.
if(arr[i]['id'] == 10002 || arr[i]['id'] == 10003){
//fetch the list values
}
I have an object that has unique keys and each key holds an object:
var object = { 'a': {
source: '5279edf0-cd7f-11e3-af07-59475a41e2e9',
target: 'f6b3faa1-ad86-11e3-9409-3dbc47429e9f',
id: [ 'bf504d02-81e2-4a92-9c5c-8101943dc36d' ],
edge_context: [ 'small' ],
statement_id: [ '09b05bc0-20ab-11e9-a5b3-9fb3da66a7cb' ],
weight: 2
},
'b': {
source: '5279edf1-cd7f-11e3-af07-59475a41e2e9',
target: 'f6b3faa1-ad86-11e3-9409-3dbc47429e9f',
id: [ 'de769846-9145-40f8-ab2d-91c0d9b82b27',
'd5723929-71a0-4dfe-bf03-94d43e358145' ],
edge_context: [ 'small' ],
statement_id:
[ '09b05bc0-20ab-11e9-a5b3-9fb3da66a7cb',
'62671510-20ab-11e9-8cbf-ef11fdb08712' ],
weight: 6
}
}
var newArray = [];
for (let item of object) {
newArray(item);
}
console.log(newArray);
I want to map it to another array where the keys will be in a sequence 0, 1, 2 etc as the usual array
I tried to use this function above but it's not working saying "object is not iterable" so how to iterate the object?
Maybe:
const mappedObject = Object.keys(object).map(
k => object[k]
)
As others have pointed out, change the structure. It could be in the following way (you will obtain an array of objects, which you will be able to access using indexes like 0, 1, 2, etc):
var objt = [
{"a": {
"source": "5279edf0-cd7f-11e3-af07-59475a41e2e9",
"target": "f6b3faa1-ad86-11e3-9409-3dbc47429e9f",
"id": [ "bf504d02-81e2-4a92-9c5c-8101943dc36d" ],
"edge_context": [ "small" ],
"statement_id": [ "09b05bc0-20ab-11e9-a5b3-9fb3da66a7cb" ],
"weight": 2
}
},
{"b": {
"source": "5279edf1-cd7f-11e3-af07-59475a41e2e9",
"target": "f6b3faa1-ad86-11e3-9409-3dbc47429e9f",
"id": [ "de769846-9145-40f8-ab2d-91c0d9b82b27",
"d5723929-71a0-4dfe-bf03-94d43e358145" ],
"edge_context": [ "small" ],
"statement_id":
[ "09b05bc0-20ab-11e9-a5b3-9fb3da66a7cb",
"62671510-20ab-11e9-8cbf-ef11fdb08712" ],
"weight": 6
}
}
];
var newArray = objt.map(element => {
const firstProperty = Object.keys(element)[0];
let objectInfo = element[firstProperty];
console.log(objectInfo);
return objectInfo;
});
console.log(newArray);
What happens here is, the only field of each object is not named the same (in one object is "a", the next one is "b", and so on) so we need to figure out to get the only property of each object in the initial array, which contains the information you need to put in another array. For doing this. Object.keys() returns you an array of the properties of an object. Considering the scenario in which we only have one property per object, we get it using Object.keys(element)[0].
Finally, we just use .map() to generate a new array.
I would use Object.values(object) but it's not supported by IE (there is a polyfill for that). Or would use Object.getOwnPropertyNames (which is supported by IE) to convert the keys to an array and map the array to another which containing the values.
var newArray = Object.getOwnPropertyNames(object).map(key => object[key])
I have JSON that I currently use for a kendo-ui chart. I need to use the data for a grid so I need to separate the nested data array of arrays into there own object. Javascript or linq.js will work fine. here is the JSON I am starting with.
customSeries = [{
"name": "Chantal Hamlet - Green Castle Homes",
"subId": "10223",
"bldId": "13551",
"data": [
[179900, 1386],
[214900, 1440],
[194500, 1496],
[217900, 1504],
[189900, 1542],
[184900, 1546],
[192500, 1570]
],
}, {
"name": "Ella Sea Condos - Sahnow Construction",
"subId": "9761",
"bldId": "27380",
"data": [
[199900, 1500]
]
}, {
"style": "smooth",
"color": "blue",
"data": [
[20000, 200],
[40000, 400],
[40000, 400]
],
"name": "Subject Property"
}]
I need to end up with 2 separate arrays.
First Array
Array1 = [{
"name": "Chantal Hamlet - Green Castle Homes",
"subId": "10223",
"bldId": "13551"
}, {
"name": "Ella Sea Condos - Sahnow Construction",
"subId": "9761",
"bldId": "27380"
}, {
"style": "smooth",
"color": "blue",
"name": "Subject Property"
}]
Second Array
Array2 = [
{
"data": [
[179900, 1386],
[214900, 1440],
[194500, 1496],
[217900, 1504],
[189900, 1542],
[184900, 1546],
[192500, 1570]
]
}, {
"data": [
[199900, 1500]
]
}, {
"data": [
[20000, 200],
[40000, 400],
[40000, 400]
]
}
]
You could use Array.prototype.map method.
var Array1 = customSeries.map(function(el) {
return {
name: el.name,
subId: el.subId,
bldId: el.bldId
};
});
var Array2 = customSeries.map(function(el) {
return {
data: el.data
};
});
Update:
The above code not work when your elements in customSeries don't have fixed keys except data.
If you using lodash, you could do this:
var Array1 = customSeries.map(function(el) {
return _.omit(el, 'data');
});
var Array2 = customSeries.map(function(el) {
return _.pick(el, 'data');
});
Depending on the length of the array, you might want to do this in a single pass. Using linq.js here won't help much for this, it'll just be added overhead with no real benefit.
If you don't mind obliterating your original data, you can process them both simultaneously by going through each of the items and add a copy of the data array to the second array while deleting the data from the item.
var array1 = data,
array2 = [];
array1.forEach(function (item) {
array2.push({
data: item.data
});
delete item.data;
});
If you'd rather keep your original data, you'll have to clone each item as you process them.
var array1 = [],
array2 = [];
data.forEach(function (item) {
var noData = yourCloneMethod(item); // replace call with preferred clone method
delete noData.data;
array1.push(noData);
array2.push({
data: item.data
});
});
You might want to look into using lodash, it has a lot of great functions for manipulating arrays and performing MapReduce functions.