var array = [];
Now, I am creating an object with post requests.
var object = {
property 1: req.body.x;
property 2: req.body.y
};
if the property 1 value(i.e. req.body.x) already exists in any of the objects in the array, it should giving a warning. Else we need to do array.push(object).
How to check for the property 1 value every time with the post request.
You can use array.Find in order to check if an object exists in the array with the same property.
const arr = [{
prop1: 'foo', // prop1 of `foo` already in array
}]
// small function so we can avoid code duplication
const existsInArray = (obj) => {
return arr.find((a) => a.prop1 === obj.prop1)
}
const obj1 = {
prop1: 'foo',
}
const obj2 = {
prop1: 'bar',
}
if (existsInArray(obj1)) {
console.warn('obj1 already in array')
} else {
arr.push(obj1)
}
if (existsInArray(obj2)) {
console.warn('obj2 already in array')
} else {
arr.push(obj2)
}
console.log(arr)
Related
Is it possible to get the deepest level object without knowing path names?
for example I have this json
const response = {
level1: {
level2: {
level3: {responseObject}
}
}
}
the levels will always only contain 1 value
but the there may be varying levels of nesting(5max)
is there anyway to alway get to the response object without using something such as response.level1.level2.level3?
note: the response object will always have the same keys
Use a recursive search
Check if the object matches the key template for a response object ("the response object will always have the same keys")
If so, you've found the response object so return it
If not, search again with the first object value (since "the levels will always only contain 1 value")
If any level search is on a non-object, bail out
const response = {
level1: {
level2: {
level3: {
I: "am",
a: "response object"
}
}
}
}
const responseObjectKeyTemplate = (["I", "a"]).sort().join(",")
const isResponseObject = (obj) =>
Object.keys(obj).sort().join(",") === responseObjectKeyTemplate
const searchLevel = (obj) => {
if (typeof obj !== "object") {
return null // not an object, bail
}
if (isResponseObject(obj)) {
return obj // found it
}
// BWAAAAAAA (Inception pun)
return searchLevel(Object.values(obj)[0])
}
console.log(searchLevel(response))
I am trying to aggregate the same key values into an array by value.
so for example I have an array of objects, like so
const data = [{foo: true},{foo: false},{bar: true},{buzz: false}]
when they get aggregated the array transforms into
[
foo: {true: [{foo: true}], false: [{foo: false}]},
bar: {true: [{bar: true}]},
buzz: {false: [{buzz: false}]}
]
the array entries is the original object.
Now I know the keys that I want to group by..
they are foo, bar, buzz and fizz.
But fizz is not part of the original array, so the return is undefined, like so
[
foo: {true:[{foo: true}], false: [{foo: false}]},
bar: {true: [{bar: true}]},
buzz: {false: A[{buzz: false}]}
fizz: {undefined: [{foo: true},{foo: false},{bar: true},{buzz: false}]}
],
how do I reduce the original array without including the fizz value that is undefined?
code here:
let v = [];
let types = ['foo', 'bar', 'buzz', 'fizz' ]
for (let x = 0; x < types.length; x++) {
let data = data.reduce((acc, i) => {
if (!acc[i[types[x]]]) {
acc[i[types[x]]] = [i]
}
else if (Array.isArray(acc[i[types[x]]])) {
acc[i[types[x]]].push(i);
}
else if (typeof acc[i[types[x]]] === 'object') {
acc[i[types[x]]] = [acc[i[types[x]]]]
acc[i[types[x]]].push(i)
}
return acc;
}, {})
v.push({ [types[x]]: data });
}
return v;
You were close, you just need to check if the property you were adding was undefined before adding. You can also check if the reduced object has any properties before adding to the result object.
Note that this may not be the most efficient way of doing it, but sometimes it's better to understand the code than it is to have highly efficient code.
const data = [{
foo: true
}, {
foo: false
}, {
bar: true
}, {
buzz: false
}];
let v = [];
let types = ['foo', 'bar', 'buzz', 'fizz']
for (let x = 0; x < types.length; x++) {
let reduced = data.reduce((acc, i) => {
// /* Added this type check */
if (!acc[i[types[x]]] && typeof i[types[x]] !== 'undefined') {
acc[i[types[x]]] = [i]
} else if (Array.isArray(acc[i[types[x]]])) {
acc[i[types[x]]].push(i);
} else if (typeof acc[i[types[x]]] === 'object') {
acc[i[types[x]]] = [acc[i[types[x]]]]
acc[i[types[x]]].push(i)
}
return acc;
}, {});
// Doesn't add a property for the type if there are no data
if (Object.keys(reduced).length) {
v.push({
[types[x]]: reduced
});
}
}
console.log(v);
Have a look at how Array.prototype.reduce works. It might be the right method to build your approach upon.
A generic way of solving the OP's problem was to iterate the provided data array. For each item one would extract its key and value. In case the item's key is listed (included) in another provided types array, one would continue creating a new data structure and collecting the currently processed item within the latter.
One does not want to iterate the types array for it will cause a unnecessarily complex lookup for the data items, each time a type item is going to be processed.
Thus a generically working (better code reuse) reduce method might be the best solution to the OP's problem ...
const sampleDataList = [
{ foo: true },
{ foo: false },
{ bar: true },
{ baz: false },
{ buzz: false },
{ baz: false },
{ bar: true }
];
// foo: {true: [{foo: true}], false: [{foo: false}]},
// bar: {true: [{bar: true}]},
// buzz: {false: [{buzz: false}]}
function collectItemIntoInclusiveKeyValueGroup(collector, item) {
const { inclusiveKeyList, index } = collector;
const firstItemEntry = Object.entries(item)[0];
const key = firstItemEntry[0];
const isProceedCollecting = ( // proceed with collecting ...
//
!Array.isArray(inclusiveKeyList) // - either for no given list
|| inclusiveKeyList.includes(key) // - or if item key is listed.
);
if (isProceedCollecting) {
let keyGroup = index[key]; // access the group identified
if (!keyGroup) { // by an item's key, ... or ...
// ...create it in case ...
keyGroup = index[key] = {}; // ...it did not yet exist.
}
const valueLabel = String(firstItemEntry[1]); // item value as key.
let valueGroupList = keyGroup[valueLabel]; // acces the group list
if (!valueGroupList) { // identified by an item's
// value, ...or create it in
valueGroupList = keyGroup[valueLabel] = []; // case it did not yet exist.
}
// push original reference into a grouped
// key value list, as required by the OP.
valueGroupList.push(item);
}
return collector;
}
console.log(
"'foo', 'bar', 'buzz' and 'fizz' only :",
sampleDataList.reduce(collectItemIntoInclusiveKeyValueGroup, {
inclusiveKeyList: ['foo', 'bar', 'buzz', 'fizz'],
index: {}
}).index
);
console.log(
"'foo', 'bar' and 'baz' only :",
sampleDataList.reduce(collectItemIntoInclusiveKeyValueGroup, {
inclusiveKeyList: ['foo', 'bar', 'baz'],
index: {}
}).index
);
console.log(
"all available keys :",
sampleDataList.reduce(collectItemIntoInclusiveKeyValueGroup, {
index: {}
}).index
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
Try something like:
const data = [{foo: true},{foo: false},{bar: true},{buzz: false}];
let v = [];
let types = ['foo', 'bar', 'buzz', 'fizz' ];
for (let x = 0; x < types.length; x++) {
let filteredlist = data.filter(function (d) {
return Object.keys(d)[0] == types[x];
});
let isTrue = 0;
let isFalse = 0;
if (filteredlist.length > 0) {
for (let i = 0; i < filteredlist.length; i++) {
let trueOrfalse = eval("filteredlist[i]." + types[x]);
if (trueOrfalse) {
isTrue++;
} else {
isFalse++;
}
}
v.push(types[x], {true: isTrue, false: isFalse});
}
}
console.log(v);
Assuming you only want to count the number of each key (e.g. true or false) you can use the following code.
I've written this as a function named 'aggregate' so that it can be called multiple times with different arguments.
const initialData = [{foo: true},{foo: true},{foo: false},{bar: true},{buzz: false}];
const types = ['foo', 'bar', 'buzz', 'fizz'];
const aggregate = (data, types) => {
const result = {};
data.forEach(item => {
// Extract key & value from object
// Note: use index 0 because each object in your example only has a single key
const [key, value] = Object.entries(item)[0];
// Check if result already contains this key
if (result[key]) {
if (result[key][value]) {
// If value already exists, append one
result[key][value]++;
} else {
// Create new key and instantiate with value 1
result[key][value] = 1;
}
} else {
// If result doesn't contain key, instantiate with value 1
result[key] = { [value]: 1 };
}
});
return result;
};
console.log(aggregate(initialData, types));
This will output the following (note I've added another {foo: true} to your initialData array for testing).
The output should also be an object (not array) so that each key directly relates to its corresponding value, as opposed to an Array which will simply place the value as the next item in the Array (without explicitly linking the two).
{
foo: { true: 2, false: 1 },
bar: { true: 1 },
buzz: { false: 1 }
}
How to modify the array object to object in javascript.
I have object obj1, change the value of details key to new object javascript
function newObj(obj1){
return Object.assign({}, ...obj1.map(e=>(e.details)));
}
var r1= this.newObj(obj1)
var obj1 = [
{
details: {
"info":["stocks","finance",""],
"sales":["analytics"]
}
}
]
var obj2 = [
{
details: {
"city":{"SG"}
}
}
]
Expected Output
//for obj1 (show only first value of array)
{
stocks: "stocks",
analytics: "analytics"
}
//obj2
{
SG: "SG"
}
The object in obj2 should have keys.
To solve this problem, we need to keep an object/map to fill it with the values to be returned by the function. Therefore, you need to iterate over each detail element and get the values of each property. Then, we can check whether it's an array or object and fill the map accordingly:
var obj1 = [
{
details: {
"info":["stocks","finance",""],
"sales":["analytics"]
}
}
]
var obj2 = [
{
details: {
"city":{name:"SG"}
}
}
]
function newObj(obj1){
let map = {};
obj1.forEach(e=>{
let details = e.details;
Object.values(details).forEach(value => {
if(Array.isArray(value) && value.length>0)
map[value[0]]=value[0];
else if(typeof value === 'object')
Object.values(value).forEach(val => { map[val]=val; });
})
});
return map;
}
var r1= this.newObj(obj1)
console.log(r1);
var r2 = this.newObj(obj2)
console.log(r2);
This question already has answers here:
How to set value to a property in a Javascript object, which is identified by an array of keys
(2 answers)
Closed 3 years ago.
I have an object that resembles this:
const obj = {
prop1: {
prop2: {
value: 'something',
...otherProps
}
},
...otherProps
}
And an array that looks like this:
const history = ['prop1', 'prop2', 'value']
How do I assign the property value of prop2 a new value in a way that would also work for any other depth.
Just loop through the property list and get each property of the object.
const obj = {
prop1: {
prop2: {
value: 'something'
}
}
};
const history = ['prop1', 'prop2', 'value'];
console.log(setPropertyValue(obj, history, "test"));
console.log(getPropertyValue(obj, history));
function getPropertyValueContainer(values, propertyList) {
var copy = propertyList.slice(), propertyName = copy.pop();
for (var property of copy) values = values[property];
return { propertyName: propertyName, values: values };
}
function getPropertyValue(values, propertyList) {
var container = getPropertyValueContainer(values, propertyList);
return container.values[container.propertyName];
}
function setPropertyValue(values, propertyList, value) {
var container = getPropertyValueContainer(values, propertyList);
return container.values[container.propertyName] = value;
}
You can use references.
So here i am taking reference of object in a variable untill i key equal to value and than adding value using that ref.
const obj = { prop1: { prop2: { value: 'something'}}}
const history = ['prop1', 'prop2', 'value']
let ref = obj;
history.forEach((e,index)=>{
if(e !== 'value' ) ref = ref[e]
})
ref.value = 'xyz'
console.log(obj)
This question already has answers here:
Remove property for all objects in array
(18 answers)
Closed 2 years ago.
I am trying to remove a property from an object array.
export class class1 {
prop1: string;
prop2: string;
prop3: string;
}
export class class2 {
myprop = [
{ prop1:'A', prop2:"1", prop3:"descr1" },
{ prop1:'B', prop2:"2", prop3:"descr2" },
{ prop1:'C', prop2:"3", prop3:"descr3" },
];
get(): class1[] {
return this.myprop ;
}
add(value: class1): void {
this.myprop.push(value);
}
}
var var1 = class2.get();
var var2 =
I would like var2 contain something like this.
[
{ prop1:'A', prop3:"descr1" },
{ prop1:'B', prop3:"descr2" },
{ prop1:'C', prop3:"descr3" },
];
Is there a way to convert/cast var1 into the above? In other words, I would like to remove prop2 from var1 object array and assign it to var2. How can I do that?
This seems like a great time to use .map()
var var1 = class2.get();
var var2 = var1.map(obj => ({prop1: obj.prop1, prop3: obj.prop3}));
Short, sweet, and does what you want.
MDN docs for .map()
You can delete object property like this e.g.
var myprop = [
{prop1: 'A', prop2: "1", prop3: "descr1"},
{prop1: 'B', prop2: "2", prop3: "descr2"},
{prop1: 'C', prop2: "3", prop3: "descr3"},
];
myprop = myprop.filter(function (props) {
delete props.prop2;
return true;
});
console.log(myprop);
Casting in TypeScript won't remove the property but only hide it in your IDE because it will be compile to JavaScript for runtime.
First of all, if you don't want to remove prop2 from var1 while deleting the property from var2 you need to clone it. For that you will need this JavaScript function:
function cloneObject(obj) {
if (obj === null || typeof obj !== 'object') {
return obj;
}
var temp = obj.constructor(); // give temp the original obj's constructor
for (var key in obj) {
temp[key] = cloneObject(obj[key]);
}
return temp;
}
Use the clone function to clone var1 and loop each object in var2 to remove property prop2. You can do so with JavaScript by combining array.forEach and delete:
var var2 = cloneObject(var1);
var2.forEach((obj) => { delete obj.prop2; });
Doing so will KEEP prop2 in var1 but REMOVE it from var2
// Use delete:
var user = {
firstname:"Jack",
lastname:"Prince",
};
var result = delete user.firstname;
console.log(result,"firstname deleted");
console.log(user);
//using Object rest spread operator
const { firstname, ...data } = user;
console.log(data);