Javascript remove array objects with duplicate properties while keeping the latest occurance - javascript

I've searched a lot for this but couldn't find anything that match my requirement.
I want to remove all the duplicates but keeping the last entry not the first.
The array is already presorted I don't want to mess with sorting
So it looks like this :
[{
name:"Joe",
status:"foo1" },
{
name:"Joe",
status:"foo2"},
{
name:"Vani",
status:"foo5"
}]
The expected output looks like:
[{
name:"Joe",
status:"foo2"},
{
name:"Vani",
status:"foo5"
}]
I'd be thankful if someone can help me!

You can simply use reduce
let arr = [{ name:"Joe", status:"foo1" }, { name:"Joe", status:"foo2"}, { name:"Vani", status:"foo5" }]
let op = arr.reduce((op,inp)=>{
op[inp.name] = inp
return op
},{})
console.log(Object.values(op))

You can make use of ES6 Map. As from Docs:
The Map object holds key-value pairs and remembers the original insertion order of the keys. Any value (both objects and primitive values) may be used as either a key or a value.
const data = [
{ name:"Joe", status:"foo1" },
{ name:"Joe", status:"foo2" },
{ name:"Vani", status:"foo5" }
];
const removeDupes = (arr, map = new Map()) => {
arr.forEach(o => map.set(o.name, o));
return [...map.values()];
};
console.log(removeDupes(data));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Try using simple forEach,
const arr = [{ name:"Joe", status:"foo1" }, { name:"Joe", status:"foo2"}, {
name:"Vani", status:"foo5" }];
let result = {};
arr.forEach((val) => { result[val.name] = val; });
console.log(Object.values(result));
Hope this helps...

The accepted answer doesn't actually keep the order, it amends the object at the initially found index
You could amend it to look like this:
const data = [
{ name:"Joe", status:"foo1" },
{ name:"Vani", status:"foo2" },
{ name:"Joe", status:"foo3" }
];
const removeDupes = (arr, map = new Map()) => {
arr.forEach((o, i) => map.set(o.name, {...o, order: i}));
return [...map.values()].sort((a, b) => a.order - b.order);
};
console.log(removeDupes(data));
Or perhaps do something more simple like:
const data = [
{ name:"Joe", status:"foo1" },
{ name:"Vani", status:"foo2" },
{ name:"Joe", status:"foo3" }
];
let newData = [];
data.forEach(x => {
newData = newData.filter(y => y.name != x.name);
newData.push(x);
});
console.log(newData);
I'll let someone else figure out a more performant solution...

Related

JavaScript Array attribute change

I have an array like this.
let arr = [
{
"ABBRIVATION":"ISB",
"name":"ISLAMABAD",
},
{
"ABBRIVATION":"RAW",
"name":"PINDI",
},
{
"ABBRIVATION":"SWB",
"name":"SWABI",
},
{
"ABBRIVATION":"AQ",
"name":"AQEEL",
},
]
I want to change it to like this
let me explain it a little. I want to assign the abbreviation directly to the name and the iterate through that array
let outout = [
{
"ISB":"ISLAMABAD"
},
{
"RAW":"ISLAMABAD"
},
{
"SWB":"SWABI"
},
{
"AQ":"AQEEL"
},
]
that is what I tried
let k = arr.map((item) => {
return item.ABB = item.name
})
console.log(k)
and here is the output
[ 'ISLAMABAD', 'PINDI', 'SWABI', 'AQEEL' ]
Here you go, use array map, simples
let arr = [
{
"ABBRIVATION":"ISB",
"name":"ISLAMABAD",
},
{
"ABBRIVATION":"RAW",
"name":"PINDI",
},
{
"ABBRIVATION":"SWB",
"name":"SWABI",
},
{
"ABBRIVATION":"AQ",
"name":"AQEEL",
},
]
let outout = arr.map(({ABBRIVATION, name}) => ({[ABBRIVATION]: name}));
console.log(outout);
Nothing more than a simple Array.prototype.map() needed.
let arr = [
{
ABBRIVATION: "ISB",
name: "ISLAMABAD",
},
{
ABBRIVATION: "RAW",
name: "PINDI",
},
{
ABBRIVATION: "SWB",
name: "SWABI",
},
{
ABBRIVATION: "AQ",
name: "AQEEL",
},
];
const result = arr.map(e => ({ [e.ABBRIVATION]: e.name }));
console.log(result);
map over the array of objects (map returns a new array) and assign the name to a new key defined by the abbreviation.
You code works the way it does because item.ABB is undefined, but you're also assigning item.name to it which does get returned, so you just get an array of names returned.
const arr=[{ABBRIVATION:"ISB",name:"ISLAMABAD"},{ABBRIVATION:"RAW",name:"PINDI"},{ABBRIVATION:"SWB",name:"SWABI"},{ABBRIVATION:"AQ",name:"AQEEL"}];
const out = arr.map(obj => {
return { [obj.ABBRIVATION]: obj.name };
});
console.log(out);
Hi I have seen people answer, but most of them use the map function, I provide some other solutions, hoping to expand the thinking
Use forEach function
const datas = [
{
"ABBRIVATION":"ISB",
"name":"ISLAMABAD",
},
{
"ABBRIVATION":"RAW",
"name":"PINDI",
},
{
"ABBRIVATION":"SWB",
"name":"SWABI",
},
{
"ABBRIVATION":"AQ",
"name":"AQEEL",
}
];
datas.forEach((obj, i, arr) => {
const{'ABBRIVATION':k, 'name':v} = obj;
arr[i] = {[k]:v};
});
console.log(datas);
Use flatMap function
const datas = [
{
"ABBRIVATION":"ISB",
"name":"ISLAMABAD",
},
{
"ABBRIVATION":"RAW",
"name":"PINDI",
},
{
"ABBRIVATION":"SWB",
"name":"SWABI",
},
{
"ABBRIVATION":"AQ",
"name":"AQEEL",
}
];
const result = datas.flatMap(obj => {
const {'ABBRIVATION':k, 'name':v} = obj;
return {[k]:v};
});
console.log(result);
this is how you suppose to do it.
arr.reduce((d, c)=>([...d, {[c.ABBRIVATION]: c.name}]),[])
let arr = [
{
"ABBRIVATION":"ISB",
"name":"ISLAMABAD",
},
{
"ABBRIVATION":"RAW",
"name":"PINDI",
},
{
"ABBRIVATION":"SWB",
"name":"SWABI",
},
{
"ABBRIVATION":"AQ",
"name":"AQEEL",
},
]
console.log(arr.reduce((data, current)=>([...data, {[current.ABBRIVATION]: current.name}]),[]))

How to add duplicate key elements in JavaScript Object?

I want to make the following newArray using by following testArray.
newArray↓
let newArray = [
{section:"business",name:["Bob","John"]},
{section:"H&R",name:["Jen","Bobby"]},
]
testArray↓
let test = [
{section:"business",name:"Bob"},
{section:"business",name:"John"},
{section:"H&R",name:"Jen"},
{section:"H&R",name:"Bobby"},
]
First of all, I tried to find some key elements using by filter method like below.
let newArray = test.filter((x:any,i,self)=>
self.indexOf(x.section)===i
)
but this code output is [].
So, how do I make code to get my expected output?
Does anyone help me?
Use Array.reduce():
let test=[{section:"business",name:"Bob"},{section:"business",name:"John"},{section:"H&R",name:"Jen"},{section:"H&R",name:"Bobby"}];
let newArray = test.reduce((acc,cur) => {
if(acc.some(el => el.section === cur.section)){
acc.forEach((el,idx) => {
if(el.section === cur.section){
acc[idx].name.push(cur.name)
}
})
}else{
cur.name = [cur.name]
acc.push(cur)
}
return acc
},[])
console.log(newArray)
you can try this
const test = [{
section: "business",
name: "Bob"
},
{
section: "business",
name: "John"
},
{
section: "H&R",
name: "Jen"
},
{
section: "H&R",
name: "Bobby"
},
];
// gather sections
const sections = {};
test.forEach(t => {
sections[t.section] = sections[t.section] || [];
sections[t.section].push(t.name);
});
// convert sessions to array
const newArray = Object.keys(sections).map(k => {
return {
section: k,
name: sections[k]
};
});
console.log(newArray);

How to consolidate an array of multiple objects into single object?

So, I have an array like this:
[
{ tags__region: "Stockholm" },
{ tags__region: "Lund" },
{ tags__region: "Mora" },
{ tags__user: "Johan" },
{ tags__user: "Eva" }
]
and I want to turn that into an object like this:
{
tags__region: ["Stockholm", "Lund", "Mora"],
tags__user: ["Johan", "Eva"]
}
Is there a way with lodash?
Are vanilla Array/Object -methods simple enough?
Keep in mind the keys on my array are unknown, so they are not always the same.
Simple Javascript.
let arr = [{
tags__region: "Stockholm"
},
{
tags__region: "Lund"
},
{
tags__region: "Mora"
},
{
tags__user: "Johan"
},
{
tags__user: "Eva"
}
];
arr = arr.reduce((acc, val) => {
let key = Object.keys(val)[0];
let value = Object.values(val)[0];
acc[key] = acc[key] ? [...acc[key],value] : [value]
return acc;
}, {})
console.log(arr);
You can use Lodash's _.mergeWith() with array spread to combine all items in the array to a single object. If the same property exists in two object, the values will be collected to an array:
const arr = [{"tags__region":"Stockholm"},{"tags__region":"Lund"},{"tags__region":"Mora"},{"tags__user":"Johan"},{"tags__user":"Eva"}]
const result = _.mergeWith({}, ...arr, (objValue = [], srcValue) =>
[...objValue, srcValue]
)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
With Lodash/fp you can generate a function (fn) using _.mergeAllWith(), and _.concat() that will do the same thing:
const fn = _.mergeAllWith(_.concat)
const arr = [{"tags__region":"Stockholm"},{"tags__region":"Lund"},{"tags__region":"Mora"},{"tags__user":"Johan"},{"tags__user":"Eva"}]
const result = fn(arr)
console.log(result)
<script src='https://cdn.jsdelivr.net/g/lodash#4(lodash.min.js+lodash.fp.min.js)'></script>

How can I merge an array of Objects with same keys in ES6 javascript?

How can I merge two arrays of Objects that have different keys pairs. I would be OK to use a library or ES6 features.
const listOfQuestions = [{
question1: {
important: true
}
}, {
question2: {
important: false
}
}]
const listOfAnswers = [{
question1: {
answer: false
}
}, {
question2: {
answer: true
}
}]
Expected result:
const result = [{
"question1": {
"important": true,
"answer": false
}
}, {
"question2": {
"important": false,
"answer": true
}
}]
I tried to use spread syntax:
const test = [...listOfQuestions, ...listOfAnswers]
But then I get something very out of what I needed:
[
{
"question1": {
"important": true
}
}, {
"question2": {
"important": false
}
}, {
"question1": {
"answer": false
}
}, {
"question2": {
"answer": true
}
}
]
Got very interesting code in the answers. I would like to mention that I also could achieve the result using the lodash method .merge().
const result = _.merge(listOfQuestions, listOfAnswers)
const listOfQuestions = [{question1:{important: true}}, {question2:{important: false}}]
const listOfAnswers = [{question1:{answer: false}}, {question2:{answer: true}}]
const result = _.merge(listOfQuestions, listOfAnswers)
console.log(result)
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.10/lodash.min.js"></script>
You could collect the inner properties of every question in an object and render a new object with only one question in a new array.
const
setHash = o => Object.entries(o).forEach(([k, v]) => Object.assign(hash[k] = hash[k] || {}, v));
var listOfQuestions = [{ question1: { important: true } }, { question2: { important: false } }],
listOfAnswers = [{ question1: { answer: false } }, { question2: { answer: true } }],
hash = Object.create(null),
result;
listOfQuestions.forEach(setHash);
listOfAnswers.forEach(setHash);
result = Object.entries(hash).map(([k, v]) => ({ [k]: v }));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
While I agree with Felix's comment in the OP that the data structure is not conducive to this operation, here is an example of merging these two arrays that assumes the object has only one key (that is the question identifier) and that the answers array always contains an item that corresponds to the questions array:
// jshint esnext: true
const listOfQuestions = [{question1:{important: true}}, {question2:{important: false}}];
const listOfAnswers = [{question1:{answer: false}}, {question2:{answer: true}}];
const merged = listOfQuestions.map((item) => {
const obj = {};
const key = Object.keys(item)[0];
const question = item[key];
const answer = listOfAnswers.find((answer) => {
const answerKey = Object.keys(answer)[0];
return key === answerKey;
})[key];
obj[key] = {...question, ...answer};
return obj;
});
console.log(merged);
Uses the spread syntax, but overall this is probably not the best way to approach this problem.
You can achieve this using the .map() function and returning a newly created array containing the bool important as well as the answer to each question.
const Q = [{question1:{important: true}}, {question2:{important: false}}]
const A = [{question1:{answer: false}}, {question2:{answer: true}}]
let testArr = Q.map(function(q, i) {
return {
['question' + (i + 1)]: {
important: q['question' + (i + 1)].important,
answer: A[i]['question' + (i + 1)].answer
}
}
}, this);
console.log(testArr)
This structure is horrible to work with!!
That being said following uses a Map to store copies of question objects then loops through answers to extend objects in Map and finally converts Map values to array
const qMap = questions.reduce((m, q) => {
const qKey = Object.keys(q)[0];
return m.set(qKey, {[qKey]: Object.assign({}, q[qKey])});
}, new Map);
answers.forEach(a => {
const qKey = Object.keys(a)[0];
qMap.get(qKey) && Object.assign(qMap.get(qKey)[qKey], a[qKey]);
});
const res = [...qMap.values()];
console.log(res)
<script>
const questions = [{
question1: {
important: true
}
}, {
question2: {
important: false
}
}]
const answers = [{
question1: {
answer: false
}
}, {
question2: {
answer: true
}
}]
</script>

convert JSON object to a different one

i have this json:
[
{
"AF28110": 33456.75,
"AF27989": 13297.26
}
]
and i want to convert it to:
[
{ "name": "AF28110", "price": 33456.75},
{ "name": "AF27989", "price": 13297.26}
]
I have tried various making it with .map() but i cannot make it work.
does anyone have any idea how to do this?
thank you
You can try following code:
let output = [];
input.forEach(obj => Object.getOwnPropertyNames(obj).forEach(key => output.push({name: key, price: obj[key]})))
Object.getOwnPropertyNames will give you names of your properties and then you can transform each name to a separate output array item.
Using map:
const data = [
{
"AF28110": 33456.75,
"AF27989": 13297.26
}
]
const out = Object.keys(data[0]).map(el => {
return { name: el, price: data[0][el] };
});
console.log(out)
Here's a way using concat, Object.keys, and map. You can take each item from the array, get the keys from that object, and then map each key to the name/price object you want. Do that for each item, then flatten the result (using concat).
Example:
const arr = [{
"AF28110": 33456.75,
"AF27989": 13297.26
}]
const result = [].concat(...arr.map(o => Object.keys(o).map(k => ({name: k, price: o[k]}))))
console.log(result);
If you have multiple objects on the array, you can use reduce
let arr = [
{"AF28110": 33456.75,"AF27989": 13297.26},
{"AF28111": 33456.20,"AF27984": 13297.88}
];
let result = arr.reduce((c, v) => c.concat(Object.entries(v).map(o => {return {name: o[0],price: o[1]}})), []);
console.log(result);
Try this,
var text = '[{"AF28110": 33456.75,"AF27989": 13297.26}]';
var obj = JSON.parse(text);
var result = [];
for (i = 0; i < obj.length; i++) {
var keys = Object.keys(obj[i]);
for (j = 0; j < keys.length; j++){
result[j] = '{ "name":' +keys[j] + ', "price":' + obj[i][keys[j]]+'}';
}
}
console.log(result);
Thanks.
Ways to achieve :
Using Object.keys method :
var jsonObj = [
{
"AF28110": 33456.75,
"AF27989": 13297.26
}
];
var res = Object.keys(jsonObj[0]).map(item => {
return {"name": item, "price": jsonObj[0][item] };
});
console.log(res);
Using Object.getOwnPropertyNames method :
var jsonObj = [
{
"AF28110": 33456.75,
"AF27989": 13297.26
}
];
var res = Object.getOwnPropertyNames(jsonObj[0]).map(item => {
return {"name": item, "price": jsonObj[0][item] };
});
console.log(res);

Categories

Resources