I'm having the below list and I would like to add only these property names PRODUCT_TYPE, PRODUCT_TERM, PRODUCT_ID in myProduct. I want to ignore rest of the properties - I've around 100 properties and want to filter only a few of them from myProduct
Please find my code below:
const obj = {
myProduct: [
{
name: "PRODUCT_PRICE",
value: "234.324",
},
{
name: "PRODUCT_NAME",
value: "Insurance",
},
{
name: "PRODUCT_TYPE",
value: "Life",
},
{
name: "PRODUCT_TERM",
value: "Long",
},
{
name: "PRODUCT_ID",
value: "AP3232343JKD",
},
{
name: "PRODUCT_ENABLED",
value: "TRUE",
},
],
};
const allowedNames = [
'PRODUCT_TYPE',
'PRODUCT_TERM',
'PRODUCT_ID'
];
const updateCertainProperties = {
PRODUCT_ID: "app.productID",
PRODUCT_ENABLED: "app.product.enabled"
};
const productName = "testProduct_3234dfasfdk3msldf23";
const environment = obj.myProduct.map((o) => {
obj.myProduct.filter(product => allowedNames.includes(product.name));
if (updateCertainProperties[o.name]) o.name = updateCertainProperties[o.name];
if (o.name === "PRODUCT_NAME") o.value = productName;
return obj.myProduct;
});
console.log(obj.myProduct)
Expected output:
[
{ name: 'PRODUCT_NAME', value: 'testProduct_3234dfasfdk3msldf23' },
{ name: 'PRODUCT_TYPE', value: 'Life' },
{ name: 'PRODUCT_TERM', value: 'Long' },
{ name: 'app.productID', value: 'AP3232343JKD' },
{ name: 'app.product.enabled', value: 'TRUE' }
]
Can someone please help me how can I achieve this? Appreciated your help in advance!
You can create an array of allowed names and filter them out using includes()
css just for prettier output
UPDATE
added updateCertainProperties object values into allowedNames array and moved filter outside environment map.
const obj = {
myProduct: [
{
name: "PRODUCT_PRICE",
value: "234.324",
},
{
name: "PRODUCT_NAME",
value: "Insurance",
},
{
name: "PRODUCT_TYPE",
value: "Life",
},
{
name: "PRODUCT_TERM",
value: "Long",
},
{
name: "PRODUCT_ID",
value: "AP3232343JKD",
},
{
name: "PRODUCT_ENABLED",
value: "TRUE",
},
],
};
const allowedNames = [
'PRODUCT_TYPE',
'PRODUCT_TERM',
'PRODUCT_NAME'
];
const updateCertainProperties = {
PRODUCT_ID: "app.productID",
PRODUCT_ENABLED: "app.product.enabled"
};
allowedNames.push(...Object.values(updateCertainProperties));
const productName = "testProduct_3234dfasfdk3msldf23";
const environment = obj.myProduct.map((o) => {
if (updateCertainProperties[o.name]) o.name = updateCertainProperties[o.name];
if (o.name === "PRODUCT_NAME") o.value = productName;
return obj.myProduct;
});
obj.myProduct = obj.myProduct.filter(product => allowedNames.includes(product.name));
console.log(obj.myProduct)
.as-console-wrapper {
max-height: unset !important;
top: 0;
}
It sounds like you're describing filtering an array, not "excluding properties". You have an array of objects, with each object consisting of a name property and value property. And you only want objects with specific values in their name property.
Using .filter on the array, it might look something like this:
obj.myProduct = obj.myProduct.filter(p => (
p.name === 'PRODUCT_TYPE' ||
p.name === 'PRODUCT_TERM' ||
p.name === 'PRODUCT_ID'));
This would filter out all elements of the array which don't match the supplied condition.
Related
I have a response value which is dynamic which i need to store in redux state,
Response consist of array of object and and name
ex :
{data:[
{name:"abc",age:"10",id:"10"}
{name:"abc",age:"15",id:"20"}
{name:"def",age:"15",id:"20"}
]
name: "abc"
}
So if the name is same I need to create array with the name.
Expected :
abc:[
{name:"abc",age:"10",id:"10"}
{name:"abc",age:"15",id:"20"}
]
something I tried
data.map(function(o) {
if(data.name ==o.name)
return name[o];
});
If you're wanting a new object with a key of the name property you could try something like this
const response = {
data: [{
name: "abc",
age: "10",
id: "10"
},
{
name: "abc",
age: "15",
id: "20"
},
{
name: "def",
age: "15",
id: "20"
},
],
name: "abc"
}
const createSet = (someData) => {
let key = someData.name
let data = someData.data.filter(e => e.name === key)
return {
[key]: data
}
}
console.log(createSet(response))
You can extract duplicated using reduce and filter :
var data = {
data:[
{name:"abc",age:"10",id:"10"},
{name:"abc",age:"15",id:"20"},
{name:"def",age:"15",id:"20"}
],
name: "abc"
}
const lookup = data.data.reduce((a, e) => {
a[e.name] = ++a[e.name] || 0;
return a;
}, {});
console.log(data.data.filter(e => lookup[e.name]));
This is the array i get:
const packages = [
{
id: '641a1690-6c8b-4ada-ae97-8d82cc4fe7a3',
name: 'com.sample',
children: {
id: 'd7384f60-e4ab-4a86-8e2e-0f66cc32f',
name: 'child.computer.com',
children: { id: 'e4ab-4a86-0f66cc32f560', name: 'child.com' }
}
},
{ id: 'd7384f60-e4ab-4a86-8e2e-0f66cc32f560', name: 'computer.com' },
{ id: 'ca7f972e-64ee-4cb0-80b9-1036fac69d32', name: 'java.util' }
];
So, it is an array of objects, and each object can have children, which again have id, name and possibly children (children is optional), and so on, it can be nested X times.
I want to change key names, id to key, name to title and children will remain children. So, my problem is that i don't know how to change keys inside children, i just change the first level and that is all.. It should be like:
{
key: '641a1690-6c8b-4ada-ae97-8d82cc4fe7a3',
title: 'com.sample',
children: {
key: 'd7384f60-e4ab-4a86-8e2e-0f66cc32f',
title: 'child.computer.com',
children: { key: 'e4ab-4a86-0f66cc32f560', title: 'child.com' }
}
}
You can do this by using Recursion.
Check if the value of the [key-value] pair from the Object#entries() call is an object.
If so, call the transformObj function again recursively for that value. Else return the value as is.
And finally convert the array of [key-value] pairs back to an object by using Object#fromEntries:
const packages = [{ id: '641a1690-6c8b-4ada-ae97-8d82cc4fe7a3', name: 'com.sample', children: { id: 'd7384f60-e4ab-4a86-8e2e-0f66cc32f', name: 'child.computer.com', children: { id: 'e4ab-4a86-0f66cc32f560', name: 'child.com' }}}, { id: 'd7384f60-e4ab-4a86-8e2e-0f66cc32f560', name: 'computer.com' }, { id: 'ca7f972e-64ee-4cb0-80b9-1036fac69d32', name: 'java.util' }];
const replacer = { "id": "key", "name" :"title"};
const transformObj = (obj) => {
if(obj && Object.getPrototypeOf(obj) === Object.prototype){
return Object.fromEntries(
Object.entries(obj)
.map(([k, v]) => [replacer[k] || k, transformObj(v)])
);
}
//Base case, if not an Object literal return value as is
return obj;
}
console.log(packages.map(o => transformObj(o)));
You can try to go through every object inside your array and recursively iterate through its keys. Then you can change the keys you want to change and iterate further through the childrens key.
const packages = [{id: '641a1690-6c8b-4ada-ae97-8d82cc4fe7a3',name:'com.sample',children: {id: 'd7384f60-e4ab-4a86-8e2e-0f66cc32f',name: 'child.computer.com',children: { id: 'e4ab-4a86-0f66cc32f560', name: 'child.com' }}},{ id: 'd7384f60-e4ab-4a86-8e2e-0f66cc32f560', name: 'computer.com' },{ id: 'ca7f972e-64ee-4cb0-80b9-1036fac69d32', name: 'java.util' }];
const renameNestedObjects = (obj) => {
Object.keys(obj).forEach((key, index) => {
if (key == "id") {
obj["key"] = obj["id"];
delete obj["id"];
}
if (key == "name") {
obj["title"] = obj["name"];
delete obj["name"];
}
if (key == "children") {
renameNestedObjects(obj["children"]);
}
});
}
console.log(packages);
packages.forEach(obj => { renameNestedObjects(obj); });
console.log(packages);
I have an array of duplicated objects in Javascript. I want to create an array of unique objects by adding the index of occurrence of the individual value.
This is my initial data:
const array= [
{name:"A"},
{name:"A"},
{name:"A"},
{name:"B"},
{name:"B"},
{name:"C"},
{name:"C"},
];
This is expected end result:
const array= [
{name:"A-0"},
{name:"A-1"},
{name:"A-2"},
{name:"B-0"},
{name:"B-1"},
{name:"C-0"},
{name:"C-1"},
];
I feel like this should be fairly simple, but got stuck on it for a while. Can you please advise how I'd go about this? Also if possible, I need it efficient as the array can hold up to 1000 items.
EDIT: This is my solution, but I don't feel like it's very efficient.
const array = [
{ name: "A" },
{ name: "A" },
{ name: "C" },
{ name: "B" },
{ name: "A" },
{ name: "C" },
{ name: "B" },
];
const sortedArray = _.sortBy(array, 'name');
let previousItem = {
name: '',
counter: 0
};
const indexedArray = sortedArray.map((item) => {
if (item.name === previousItem.name) {
previousItem.counter += 1;
const name = `${item.name}-${previousItem.counter}`;
return { name };
} else {
previousItem = { name: item.name, counter: 0};
return item;
}
});
Currently you are sorting it first then looping over it, which may be not the most efficient solution.
I would suggest you to map over it with a helping object.
const a = [{name:"A"},{name:"A"},{name:"A"},{name:"B"},{name:"B"},{name:"C"},{name:"C"},], o = {};
const r = a.map(({ name }) => {
typeof o[name] === 'number' ? o[name]++ : o[name] = 0;
return { name: `${name}-${o[name]}` };
});
console.log(r);
Keep a counter, and if the current name changes, reset the counter.
This version mutates the objects. Not sure if you want a copy or not. You could potentially sort the array by object name first to ensure they are in order (if that's not already an existing precondition.)
const array = [
{ name: "A" },
{ name: "A" },
{ name: "A" },
{ name: "B" },
{ name: "B" },
{ name: "C" },
{ name: "C" },
];
let name, index;
for (let i in array) {
index = array[i].name == name ? index + 1 : 0;
name = array[i].name;
array[i].name += `-${index}`;
}
console.log(array);
Another way, if you don't want to sort, and don't want to mutate any objects, is to use a map and keep track of the current index for each object.
const array = [
// NOTE: I put the items in mixed up order.
{ name: "A" },
{ name: "C" },
{ name: "A" },
{ name: "B" },
{ name: "A" },
{ name: "C" },
{ name: "B" },
];
let index = {};
let next = name => index[name] = index[name] + 1 || 0;
let result = array.map(obj => ({ ...obj, name: obj.name + '-' + next(obj.name) }));
console.log(result);
I have an array of objects, I need to delete a complete object based on the id
Input :
filters: [
{
key: "status",
label: "En attente",
value: "waiting",
id: 0
},
{
key: "dateDue[min]",
label: "15/12/2019",
value: "15/12/2019",
id: 1
},
{
key: "dateDue[max]",
label: "02/02/2020",
value: "02/02/2020",
id: 2
},
{
key: "bien",
values: [
{
label: "Studio Bordeaux",
value: 36,
id: 3
},
{
label: "Studio 2",
value: 34,
id: 184
}
]
},
{
key: "type",
values: [
{
type: "receipts",
label: "Loyer",
value: "loyer",
id: 4
},
{
type: "receipts",
label: "APL",
value: "apl",
id: 5
},
{
type: "spending",
label: "taxes",
value: "taxes",
id: 6
}
]
}
]
So I created a removeItem method with the id that must be deleted in parameters
removeItem method :
removeItem = (e, id) => {
const { filters } = this.state;
const remove = _.reject(filters, el => {
if (!_.isEmpty(el.values)) {
return el.values.find(o => o.id === id);
}
if (_.isEmpty(el.values)) {
return el.id === id;
}
});
this.setState({
filters: remove
});
};
I use lodash to make my job easier and more specifically _.reject
My issue is the following :
I manage to correctly delete the classic objects for example
{
key: "status",
label: "En attente",
value: "waiting",
id: 0
}
but my method however does not work for objects of the following form
{
key: "bien",
values: [
{
label: "Studio Bordeaux",
value: 36,
id: 3
},
{
label: "Studio 2",
value: 34,
id: 184
}
]
},
currently the whole object is deleted and not only the object in the values array according to its id
Here is my codesandbox!
thank you in advance for your help
EDIT
I found a solution with lodash (compact), I share my solution here :
removeIdFromCollection = id => {
const { filters } = this.state;
const newFilters = [];
_.map(filters, filter => {
if (filter.values) {
const valuesTmp = _.compact(
_.map(filter.values, value => {
if (value.id !== id) return value;
})
);
if (!_.isEmpty(valuesTmp)) {
return newFilters.push({
key: filter.key,
values: valuesTmp
});
}
}
if (filter.id && filter.id !== id) return newFilters.push(filter);
});
return newFilters;
};
removeItem = id => e =>
this.setState({
filters: this.removeIdFromCollection(id)
});
The values false, null, 0, "", undefined, and NaN are removed with lodash compact (_.compact(array))
Here is my updated codesandbox
You will need to filter the filters array and each values separately. Below is a recursive function which will remove items with the given id from the filters array and from the values property.
PS. This example is not using Lodash as I think it is not needed in this case.
removeIdFromCollection = (collection, id) => {
return collection.filter(datum => {
if (Array.isArray(datum.values)) {
datum.values = this.removeIdFromCollection(datum.values, id);
}
return datum.id !== id;
});
}
removeItem = (e, id) => {
const { filters } = this.state;
this.setState({
filters: this.removeIdFromCollection(filters, id),
});
};
The problem would be the structure of the object. You'll need to refactor for that inconvenient array out of nowhere for uniformity:
// Example
filters: [
...
{
key: "type",
values: [
{
type: "receipts",
label: "Loyer",
value: "loyer",
id: 4
},
...
]
...
}
// could be
filters: [
...
{
key: "type-receipts",
label: "Loyer",
value: "loyer",
id: 4
}
...
]
Repeat the pattern on all of it so you could just use the native array filter like this:
const newFilters = filters.filter(v => v.id !== id);
this.setState({
filters: newFilters,
});
I found a solution with lodash, I share it with you here :
removeIdFromCollection = id => {
const { filters } = this.state;
const newFilters = [];
_.map(filters, filter => {
if (filter.values) {
const valuesTmp = _.compact(
_.map(filter.values, value => {
if (value.id !== id) return value;
})
);
if (!_.isEmpty(valuesTmp)) {
return newFilters.push({
key: filter.key,
values: valuesTmp
});
}
}
if (filter.id && filter.id !== id) return newFilters.push(filter);
});
return newFilters;
};
removeItem = id => e =>
this.setState({
filters: this.removeIdFromCollection(id)
});
Here is my updated codesandbox
I am working on an application where I need to get combine the object of same department based on the
conditions provided in the second Array and attach the relation to the object.
let inArr1 = [{"D1D2":"AND"},{"D3D4":"OR"}]
let inArr2 =[{"ID":"1","NAME":"KEN","DEPT1":"CSE"},
{"ID":"2","NAME":"MARK","DEPT2":"IT"},
{"ID":"3","NAME":"TOM","DEPT3":"ECE"},
{"ID":"4","NAME":"SHIV","DEPT4":"LIB"},
{"ID":"5","NAME":"TIM","DEPT5":"SEC"}
]
Output
outArr ={
[{"ID":"1","NAME":"KEN","DEPT1":"CSE","REL":"AND"},
{"ID":"2","NAME":"MARK","DEPT2":"IT","REL":"AND"}], //Arr1
[{"ID":"3","NAME":"TOM","DEPT3":"ECE","REL":"OR"},
{"ID":"4","NAME":"SHIV","DEPT4":"LIB","REL":"OR"}], //Arr2
[{"ID":"5","NAME":"TIM","DEPT5":"SEC"}] //Arr3
}
Code:
let condArr=[],outArr,i=1;
inArr1.forEach(condt => {
let dept = Object.keys(condt)[0];
let tmparr = dept.split("D");
tmparr.shift()
condArr.push(tmparr)
});
inArr2.forEach(condt => {
if(condArr.includes(inArr2.D+i)){
i++;
outArr.push(inArr2);
}
});
Your code has a bit confused logic, i would suggest rather this
let inArr1 = [{"D1D2":"AND"},{"D3D4":"OR"},{"D5D6":"AND"}]
let inArr2 =[{"ID":"1","NAME":"KEN","DEPT1":"CSE"},
{"ID":"2","NAME":"MARK","DEPT2":"IT"},
{"ID":"3","NAME":"TOM","DEPT3":"ECE"},
{"ID":"4","NAME":"SHIV","DEPT4":"LIB"},
{"ID":"5","NAME":"TIM","DEPT5":"SEC"},
{"ID":"6","NAME":"TLA","DEPT6":"SEC"},
]
// first lets create object of ids as keys and conditions as values
const [keys, conditions] = inArr1.reduce((agg, cond, index) => {
Object.entries(cond).forEach(([key, value]) => {
key.split('D').forEach(v => { if (v) agg[0][v] = { value, index }})
agg[1].push([])
})
return agg
}, [{}, []]) // {1: "AND", 2: "AND", 3: "OR", 4: "OR"}
conditions.push([])
// and now just map over all elements and add condition if we found id from the keys
inArr2.forEach(item => {
const cond = keys[item.ID]
if (cond) conditions[cond.index].push({...item, REL: cond.value})
else conditions[conditions.length - 1].push(item)
})
const res = conditions.filter(v => v.length)
console.log(res)
You could store the goups by using the ID and use new objects.
let inArr1 = [{ D1D2: "AND" }, { D3D4: "OR" }],
inArr2 = [{ ID: "1", NAME: "KEN", DEPT1: "CSE" }, { ID: "2", NAME: "MARK", DEPT2: "IT" }, { ID: "3", NAME: "TOM", DEPT3: "ECE" }, { ID: "4", NAME: "SHIV", DEPT4: "LIB" }, { ID: "5", NAME: "TIM", DEPT5: "SEC" }],
groups = inArr1.reduce((r, o) => {
Object.entries(o).forEach(([k, REL]) => {
var object = { REL, group: [] };
k.match(/[^D]+/g).forEach(id => r[id] = object);
});
return r;
}, {}),
grouped = inArr2.reduce((r, o) => {
var { REL, group } = groups[o.ID] || {};
if (group) {
if (!group.length) r.push(group);
group.push(Object.assign({}, o, { REL }));
} else {
r.push([o]);
}
return r;
}, []);
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
can try other solution:
let inArr1 = [{ D1D2: "AND" }, { D3D4: "OR" }, { D6D7: "XOR" }];
let inArr2 = [
{ ID: "1", NAME: "KEN", DEPT1: "CSE" },
{ ID: "2", NAME: "MARK", DEPT2: "IT" },
{ ID: "3", NAME: "TOM", DEPT3: "ECE" },
{ ID: "4", NAME: "SHIV", DEPT4: "LIB" },
{ ID: "5", NAME: "TIM", DEPT5: "SEC" },
{ ID: "9", NAME: "BAR", DEPT5: "XYZ" },
{ ID: "6", NAME: "FOO", DEPT5: "XYZ" },
];
let unmatchedArr = []
let matchedArr = inArr2.reduce((acc, obj) => {
// getting index matched from inArr1 objects key
const indexMatched = getIndexMatch(obj.ID);
// creating index if not exists
if (!acc[indexMatched] && indexMatched !== null) acc[indexMatched] = [];
// if some index matched it merge current obj with DEL property with inArr1[indexMatched] key => value
return indexMatched !== null
? acc[indexMatched].push({
...obj,
DEL: inArr1[indexMatched][Object.keys(inArr1[indexMatched])[0]]
})
// pushing on unmatchedArr
: unmatchedArr.push(obj)
, acc
}, []);
function getIndexMatch(id) {
for (const [index, obj] of inArr1.entries()) {
for (const key of Object.keys(obj)) {
// spliting only digits of the current key of object
if (key.match(/\d/g).includes(id)) return index; // returning index of inArr1 if is included
}
}
return null;
}
// merging arrays
const result = [...matchedArr, unmatchedArr];
console.log(result);