How to get into an object that is in an array - javascript

Let's say I have an array like this :
arrayOfObject = [{item: {this: is, that: is}}, {item2: {this: is, that: is}}]
I'm trying to access item and item2 without having to use a 0/1 index. I'd like to be able to say arrayOfObjects[item] to get into the object. Is this possible?

You can use Array.find.
arrayOfObject = [{
item: {
this: 'is',
that: 'is'
}
}, {
item2: {
this: 'is',
that: 'is'
}
}]
console.log(arrayOfObject.find(ob => ob['item']));
console.log(arrayOfObject.find(ob => ob['item2']));

var arrayOfObject = [{
"item": {
"this": "is",
"that": "is"
}
}, {
"item2": {
"this": "is",
"that": "is"
}
}];
var itemObject = {};
arrayOfObject.forEach(function(value) {
var filterObject = Object.keys(value).filter(val => val.indexOf("item") != -1);
if (filterObject.length > 0) {
filterObject.forEach(key => {
itemObject[key] = itemObject[key] || [];
itemObject[key].push(value[filterObject[0]]);
});
}
});
console.log(itemObject.item); //item
console.log(itemObject.item2); //item

You can not do exactly this but something similar where you would "convert" your array to an object and then use the keys to access the values:
arrayOfObject = [{ item: { this: "a", that: "b" } }, { item2: { this: "c", that: "d" } }]
const arrayToObject = arrayOfObject.reduce((r,c) => Object.assign(r,c), {})
console.log(arrayToObject['item'])
console.log(arrayToObject['item2'])
In the snippet above we convert the arrayOfObject to arrayToObject and then simply access the values via the keys.
Otherwise what you are trying to do is not possible since you can only access values from an array by index or via some kind of a function which would traverse it and get you the entry, like find etc.

Yeah sure it is possible:
var result = arrayOfObject.map(a => a.item);
or
var result = arrayOfObject.map(a => a.item2);

Related

Javascript: From JSON array of strings in the form of key:value to array of objects

say that I receive this JSON array from an API call.
[
"{'apple': 'enabled'}",
"{'banana': 'disabled'}"
]
How do I transform it into this:
[
{
label: 'apple',
value: 'enabled'
},
{
label: 'banana',
value: 'disabled'
}
]
The number of fields and the values are of course variable.
With JSON5.parse() I can transform it into this:
[
{
apple: 'enabled',
},
{
banana: 'disabled'
}
]
But this is still not what I need.
How can I achieve the transformation I need, without hacky workarounds that might change the values inside?
Thank you
const apiArray = [
"{'apple': 'enabled'}",
"{'banana': 'disabled'}"
];
const returnArray = [];
for (const element of apiArray) {
const parsedObj = JSON.parse(element);
const label = Object.keys(element)[0];
const value = parsedObj[label];
returnArray.push({"label": label, "value": value});
}
This inspects every element of the initial array on its own and extracts the label and the value. These then get pushed into the returnArray in the correct format.
I managed to make it work with this:
(Thanks #Alexander)
data.map(el=>{
const parsed = JSON5.parse(el)
return{
label: Object.keys(parsed)[0],
value: Object.values(parsed)[0]
}
})
However, it is not very clean.
you can try this
var newArr = [];
apiArray.forEach((element) => {
let obj = JSON.parse(element.replaceAll("'", '"'));
newArr.push({ label: Object.keys(obj)[0], value: Object.values(obj)[0] });
});
console.log(JSON.stringify(newArr));
you can try something like this :
myArray.map((data) => {
const parsedData = JSON.parse(data);
return {
label: Object.keys(parsedData).join(),
value: Object.values(parsedData).join(),
};
});
Output :
[{
"label": "apple",
"value": "enabled"
},
{
"label": "banana",
"value": "disabled"
}]

Transform an array of objects by removing object properties not contained in another array

A long title, so I´ll explain the problem by example. I have an array of objects:
const myObjects = [
{
id: 1,
name: "a",
stuff: "x"
},
{
id: 2,
name: "b",
stuff: "y"
},
];
Then I have another array of objects like this:
const myTemplate=[
{
desiredProperty: "name",
someOtherProperty: "..."
},
{
desiredProperty: "stuff",
someOtherProperty: "..."
},
];
Now I want to transform myObjects array to new one, so that the individual objects contain only the properties listed in desiredProperty of each object in myTemplate.
The result should look like this:
myResult = [
{
name: "a",
stuff: "x"
},
{
name: "b",
stuff: "y"
}
]
How to achieve this?
This approach lets you partially apply the template to get back a reusable function to run against multiple sets of inputs:
const convert = (template, keys = new Set (template .map (t => t .desiredProperty))) => (xs) =>
xs .map (
(x) => Object .fromEntries (Object .entries (x) .filter (([k, v]) => keys .has (k)))
)
const myObjects = [{id: 1, name: "a", stuff: "x"}, {id: 2, name: "b", stuff: "y"}]
const myTemplate= [{desiredProperty: "name", someOtherProperty: "..."}, {desiredProperty: "stuff", someOtherProperty: "..."}]
console .log (
convert (myTemplate) (myObjects)
)
But I agree with the comment that the template here is better expressed as an array of keys to keep.
The following code creates a Set of the keys you want to keep. Then, we map over your myObjects array and only keep the object keys that are in the toKeep Set.
const myObjects=[{id:1,name:"a",stuff:"x"},{id:2,name:"b",stuff:"y"}];
const myTemplate=[{desiredProperty:"name",someOtherProperty:"..."},{desiredProperty:"stuff",someOtherProperty:"..."}];
const toKeep = new Set(myTemplate.map(t => t.desiredProperty));
const newObjs = myObjects.map(o => {
const obj = {};
for (let key in o) {
if (toKeep.has(key)) {
obj[key] = o[key];
}
}
return obj;
});
console.log(newObjs);

how to push into an array with javascript?

I'm trying to add into an array. I don't know how to traverse and add objects correctly.
I have data array:
const data = [
{
1: "Apple",
2: "Xiaomi"
}
];
const list = [];
data.forEach(function(key, value) {
console.log("key", key);
})
console.log(list)
I want this effect to be as follows:
list: [{
{
value: 1,
title: 'Apple'
},
{
value: 2,
title: 'Xiaomi'
}
}]
Your expected output is invalid. You can first retrieve all the values from the object with Object.values(). Then use Array.prototype.map() to form the array in the structure you want.
Try the following way:
const data = [
{
1: "Apple",
2: "Xiaomi"
}
];
const list = Object.values(data[0]).map((el,i) => ({value: i+1, title: el})) ;
console.log(list);
You can use the existing key of the object with Object.entries() like the following way:
const data = [
{
1: "Apple",
2: "Xiaomi"
}
];
const list = Object.entries(data[0]).map(item => ({value: item[0], title: item[1]}));
console.log(list);
I'll go ahead and make the assumption that data is an object of key/value pairs and you want to transform it to an array of objects.
// Assuming you have an object with key/value pairs.
const data = {
1: "Apple",
2: "Xiaomi"
};
// Convert the data object into an array by iterating over data's keys.
const list = Object.keys(data).map((key) => {
return {
value: key,
title: data[key]
}
});
console.log(list)
Output:
[
{
value: '1',
title: 'Apple'
},
{
value: '2',
title: 'Xiaomi'
}
]
If you actually need value to be numbers instead of strings, you can do it this way:
const list = Object.keys(data).map((key) => {
return {
value: Number(key),
title: data[key]
}
});
And if you are OK with using a more modern version of JavaScript (ECMAScript 2017) this works nicely:
const data = {
1: "Apple",
2: "Xiaomi"
};
// Using Object.entries gives you the key and value together.
const list = Object.entries(data).map(([value, title]) => {
return { value, title }
});
You could do something like this:
const data = ['Apple', 'Xiaomi'];
const result = data.map((item, index) => ({value: index, title: item}));
console.log(result);
If the idea is to turn key names into values and those are not necessarily autoincremented numbers you might want to look at Object.entries():
const data = {1: "Apple", 2: "Xiaomi"};
const res = Object.entries(data).map(entry => ({value: entry[0], title: entry[1]}));
console.log(res);

array map, map array as a key of an array

I know the title might sounds confusing, but i'm stuck for an hour using $.each. Basically I have 2 arrays
[{"section_name":"abc","id":1},{"section_name":"xyz","id":2}];
and [{"toy":"car","section_id":1},{"tool":"knife","section_id":1},{"weapons":"cutter","section_id":2}];
How do I put one into another as a new property key like
[{
"section_name": "abc",
"id": 1,
"new_property_name": [{
"toy": "car"
}, {
"tool": "knife"
}]
}, {
"section_name": "xyz",
"id": 2,
"new_property_name": [{
"weapon": "cutter"
}]
}]
ES6 Solution :
const arr = [{"section_name":"abc","id":1},{"section_name":"xyz","id":2}];
const arr2 = [{"toy":"car","id":1},{"tool":"knife","id":1},{"weapons":"cutter","id":2}];
const res = arr.map((section,index) => {
section.new_property_name = arr2.filter(item => item.id === section.id);
return section;
});
EDIT : Like georg mentionned in the comments, the solution above is actually mutating arr, it modifies the original arr (if you log the arr after mapping it, you will see it has changed, mutated the arr and have the new_property_name). It makes the .map() useless, a simple forEach() is indeed more appropriate and save one line.
arr.forEach(section => {
section.new_property_name = arr2.filter(item => item.id === section.id));
});
try this
var data1 = [{"section_name":"abc","id":1},{"section_name":"xyz","id":2}];
var data2 = [{"toy":"car","id":1},{"tool":"knife","id":1},{"weapons":"cutter","id":2}];
var map = {};
//first iterate data1 the create a map of all the objects by its ids
data1.forEach( function( obj ){ map[ obj.id ] = obj });
//Iterate data2 and populate the new_property_name of all the ids
data2.forEach( function(obj){
var id = obj.id;
map[ id ].new_property_name = map[ id ].new_property_name || [];
delete obj.id;
map[ id ].new_property_name.push( obj );
});
//just get only the values from the map
var output = Object.keys(map).map(function(key){ return map[ key ] });
console.log(output);
You could use ah hash table for look up and build a new object for inserting into the new_property_name array.
var array1 = [{ "section_name": "abc", "id": 1 }, { "section_name": "xyz", "id": 2 }],
array2 = [{ "toy": "car", "section_id": 1 }, { "tool": "knife", "section_id": 1 }, { "weapons": "cutter", "section_id": 2 }],
hash = Object.create(null);
array1.forEach(function (a) {
a.new_property_name = [];
hash[a.id] = a;
});
array2.forEach(function (a) {
hash[a.section_id].new_property_name.push(Object.keys(a).reduce(function (r, k) {
if (k !== 'section_id') {
r[k] = a[k];
}
return r;
}, {}));
});
console.log(array1);
Seems like by using Jquery $.merge() Function you can achieve what you need. Then we have concat function too which can be used to merge one array with another.
Use Object.assign()
In your case you can do it like Object.assign(array1[0], array2[0]).
It's very good for combining objects, so in your case you just need to combine your objects within the array.
Example of code:
var objA = [{"section_name":"abc","id":1},{"section_name":"xyz","id":2}];
var objB = [{"toy":"car","section_id":1},{"tool":"knife","section_id":1},{"weapons":"cutter","section_id":2}];
var objC = Object.assign({},objA[0],objB[0]);
console.log(JSON.stringify(objC));// {"section_name":"abc","id":1,"toy":"car","section_id":1}
For more info, you can refer here: Object.assign()
var firstArray = [{"section_name":"abc","id":1},{"section_name":"xyz","id":2}],
secondArray = [{"toy":"car","section_id":1},{"tool":"knife","section_id":1},{"weapons":"cutter","section_id":2}];
var hash = Object.create(null);
firstArray.forEach(s => {
hash[s.id] = s;
s['new_property_name'] = [];
});
secondArray.forEach(i => hash[i['section_id']]['new_property_name'].push(i));
console.log(firstArray);

Finding an array's objects that are not present in another array by property

I'm looking for a way to find any objects in one array that are not present in another array based upon that object's property. What's the best way to do this with jQuery or underscore?
Given the following example:
"array1":[
{"testProperty":"A"},
{"testProperty":"B"},
{"testProperty":"C"}
]
"array2":[
{"testProperty":"A", "User":"Smith"},
{"testProperty":"B", "User":"Smith"},
]
I would want to return the third object from array1 whose testProperty is "C" since it's not present in array2.
I was able to find several examples of this issue here on stackoverflow, but not when needing to do so using properties from those objects.
I'm not sure if this counts, but if you can use lodash instead of underscore, there is a nice function called differenceBy:
var _ = require("lodash");
var array1 = [
{"testProperty":"A"},
{"testProperty":"B"},
{"testProperty":"C"}
]
var array2 = [
{"testProperty":"A", "User":"Smith"},
{"testProperty":"B", "User":"Smith"}
]
var result = _.differenceBy(array1, array2, function(item) {
return item["testProperty"]
});
console.log(result);
A proposal in plain Javascript with a hash table for look-up.
var data = { "array1": [{ "testProperty": "A" }, { "testProperty": "B" }, { "testProperty": "C" }], "array2": [{ "testProperty": "A", "User": "Smith" }, { "testProperty": "B", "User": "Smith" }, ] },
result = data.array1.filter(function (a) {
return !this[a.testProperty];
}, data.array2.reduce(function (r, a) {
r[a.testProperty] = true;
return r;
}, Object.create(null)));
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
You can use filter with map
var a = {'array1': [{"testProperty":"A"}, {"testProperty":"B"}, {"testProperty":"C"}], 'array2': [{"testProperty":"A", "User":"Smith"}, {"testProperty":"B", "User":"Smith"}]};
var result = a.array1.filter(function(e) {
return a.array2.map(el => { return el.testProperty}).indexOf(e.testProperty) == -1;
});
console.log(result);
here's a version in plain es6 js using filter and some method:
array1 = [
{"testProperty":"A"},
{"testProperty":"B"},
{"testProperty":"C"}
];
array2 =[
{"testProperty":"A", "User":"Smith"},
{"testProperty":"B", "User":"Smith"},
]
var r = array1.filter(x =>
! Object.keys(x).some(z =>
array2.some(w =>
Object.keys(w).some(y => y === z && w[y] === x[z])
)));
document.write(JSON.stringify(r))
You could use underscore's reject and some to get what you want:
var result = _.reject(array1, item => _.some(array2, {testProperty: item.testProperty}));
If performance is a concern and testProperty is an unique key of the objects in array2 then you could create a hash using indexBy and check for the result using has:
var hash = _.indexBy(array2, 'testProperty');
var result = _.reject(array1, item => _.has(hash, item.testProperty));

Categories