Javascript - Get a corresponding object between two arrays - javascript

I have the following arrays:
First array:
const dummyJSON = [
{
id: 1,
sponsor_date: '2020-08-16T22:45:03.154Z'
},
{
id: 2,
sponsor_date: '2020-09-16T22:45:03.154Z'
},
{
id: 3,
sponsor_date: '2020-09-01T22:45:03.154Z'
}
]
Second array:
const validated = [ true, false, false ]
And I wanted to get the object (dummyJSON.id) when the corresponding (validated) array item is true.
Basically, if the first item in the validate [0] array has a value of "true", then I would like to have the corresponding [0] item's id value in the dummyJSON array.

You can use Array#reduce to get array of validated ids.
It will basically loop over every element and if the index of currently iterated object corresponds to the truthy value inside validated with the very same index, the object's id will be pushed to the result.
const dummyJSON = [
{ id: 1, sponsor_date: '2020-08-16T22:45:03.154Z' },
{ id: 2, sponsor_date: '2020-09-16T22:45:03.154Z' },
{ id: 3, sponsor_date: '2020-09-01T22:45:03.154Z' }
];
const validated = [true, false, false];
const validatedIds = dummyJSON
.reduce((s, { id }, i) => (validated[i] ? s.push(id) : s, s), []);
console.log(validatedIds);

If your goal is just to get the validated items, use filter:
const valid = dummyJSON.filter((item, index) => validated[index]);
If you just want the ids, add a map call:
const valid = dummyJSON.filter((item, index) => validated[index]);
const ids = valid.map(x => x.id);
This could be done in a single line if you prefer, by chaining the map call:
const ids = dummyJSON.filter((item, index) => validated[index]).map(x => x.id);
const dummyJSON = [
{ id: 1, sponsor_date: '2020-08-16T22:45:03.154Z' },
{ id: 2, sponsor_date: '2020-09-16T22:45:03.154Z' },
{ id: 3, sponsor_date: '2020-09-01T22:45:03.154Z' }
];
const validated = [ true, false, false ];
// source objects
console.log(dummyJSON.filter((_, index) => validated[index]));
// just the ids
console.log(dummyJSON.filter((_, index) => validated[index]).map(x => x.id));

No need for reduce, filter can do that just as well and faster :
const validated = [ true, false, false ]
const dummyJSON = [
{
id: 1,
sponsor_date: '2020-08-16T22:45:03.154Z'
},
{
id: 2,
sponsor_date: '2020-09-16T22:45:03.154Z'
},
{
id: 3,
sponsor_date: '2020-09-01T22:45:03.154Z'
}
]
// To get all validated objects from dummy JSON
const validatedJSON = dummyJSON.filter((obj, index) => validated[index])
// To extract just the ID's
const validatedJSONIds = validatedJSON.map(json => json.id)

Related

Concatenate two arrays of objects and remove repeated data from an attribute

I have 2 arrays of objects. One array receives the data from the API and renders it in the application, the other receives the data from localStorage, which are data from the first and which have been changed and stored in localStorage. I want to concatenate these two arrays, but I need to remove the repeated data in order not to render the same object twice.
example of what I hope:
dado1 = [
{customer: {
purchased: false,
id: 1
}},
{customer: {
purchased: false,
id: 2
}}
]
dado2 = [
{customer: {
purchased: true,
id: 1
}}
]
dado3 = dado1.concat (dado2)
result:
dado3 = [
{customer: {
purchased: true,
id: 1
}},
{customer: {
purchased: false,
id: 2
}}
]
I am not able to compare the two arrays. I've thought of several ways, but I always fail
some thing like that ?
const dado1 =
[ { customer: { purchased: false, id: 1 } }
, { customer: { purchased: false, id: 2 } }
]
const dado2 =
[ { customer: { purchased: true, id: 1 } }
]
const dado3 = dado1.map(el=>
{
let nv = dado2.find(x=>x.customer.id === el.customer.id )
return nv? nv : el
})
console.log( dado3 )
.as-console-wrapper { max-height: 100% !important; top: 0; }
but be carrefull, this is array of object of object so prefer to use
const dado3 = dado1.map(el=>
{
let nv = dado2.find(x=>x.customer.id === el.customer.id )
return nv? JSON.parse(JSON.stringify(nv)) : JSON.parse(JSON.stringify(el))
})
if you want a real new array
You can make your customer objects unique by mapping them by the id field, and ensuring that entries from the 2nd object take precedence (this will prefer local storage over api results):
let mergeCustomerData = (arr1, arr2) => {
// Both arrays are converted to maps, where the `item.customer.id` property determines the key
[ arr1, arr2 ] = [ arr1, arr2 ].map(arr => new Map(arr.map(v => [ v.customer.id, v ])));
// Merge these Maps into one (preference determined by the order of `arr1` and `arr2`)
let merged = new Map([ ...arr1, ...arr2 ]);
// Return the merged values, converted back to an Array
return [ ...merged ].map(([ id, v ]) => v);
};
let dado1 = [
{ customer: { purchased: false, id: 1 } },
{ customer: { purchased: false, id: 2 } }
];
let dado2 = [
{ customer: { purchased: true, id: 1 } }
];
console.log(mergeCustomerData(dado1, dado2));
Collect the ids from the second array. Take as result the second array plus all elements from the first array which have a id that is not in the stored ids.
dado1 = [
{customer: { purchased: false, id: 1 }},
{customer: { purchased: false, id: 2 }}
];
dado2 = [
{customer: { purchased: true, id: 1 }},
{customer: { purchased: true, id: 5 }}
];
function concatDado( dado1, dado2) {
let result = dado2;
let ids = [];
dado2.forEach(element => ids.push(element.customer.id));
dado1.forEach(element => {
id = element.customer.id;
if ( ids.indexOf(id) == -1 )
result.push(element);
});
return result;
}
console.log( concatDado( dado1, dado2));

How to compare two different arrays which has different property names and remove unmatched ones in javascript?

I havve two different arrays with different property names like below
arrayA = [
{ id: 20, name: 'Jason' },
{ id: 15, name: 'Harry' },
{ id: 5, name: 'Clara' },
{ id: 9, name: 'Melonie' }
]
arrayB = [
{ courseID: 12, studentID: 20 },
{ courseID: 12, studentID: 15 }
]
I want to compare these two different arrays and remove unmatched ids from arrayA. For comparison, id field of arrayA and studentID field of arrayB matters. if these fileds aren't equal to each other, they should be removed from arrayA.
Expected is below
arrayA = [{id: 20, name: 'Jason' }, { id: 15, name: 'Harry' }]
Here is what I tried below but didn't work. Gave me empty array.
filteredElements = this.arrayA.map(e => e.id).filter(
val => this.arrayB.indexOf(val.studentID) !== -1
);
You can do that in following steps:
Use map() on arrayB and create array of courseID.
Then create a Set() from that Array
Then use filter() arrayA and check whether id of object exists in above created Set or not using Set.prototype.has()
const arrayA = [{id:20,name:'Jason'},{id:15,name:'Harry'},{id:5,name:'Clara'},{id:9,name:'Melonie'}]
const arrayB =[{courseID:12,studentID:20},{courseID:12,studentID:15}];
const ids = new Set(arrayB.map(x => x.studentID));
const res = arrayA.filter(x => ids.has(x.id));
console.log(res);
let arrayA = [{id: 20,name: 'Jason'},{id: 15,name: 'Harry'},{id: 5,name: 'Clara'},{id: 9,name: 'Melonie'}]
let arrayB = [{courseID: 12,studentID: 20},{courseID: 12,studentID: 15}];
let filtered=arrayA.filter(obj =>{ if(arrayB.find(course => course.studentID == obj.id))return true;return false;
});
console.log(filtered);
Try this:
var studentIds = arrayB.map(course => course.studentID);
var result = arrayA.filter(student => studentIds.includes(student.id));
The variable result contains your result.
Create a dictionary from courseMembers, keyed on studentID, to enable O(1) lookup.
Filter students according to the dictionary.
const students = [{id:20,name:'Jason'},{id:15,name:'Harry'},{id:5,name:'Clara'},{id:9,name:'Melonie'}]
const courseMembers = [{courseID:12,studentID:20},{courseID:12,studentID:15}]
function withCourses(students, courseMembers) {
const map = courseMembers.reduce((acc, {studentID}) =>
(acc[studentID] = true, acc), {})
return students.filter(({id}) => map[id])
}
const result = withCourses(students, courseMembers)
console.log(result) // [{ id:20, name:"Jason" },{ id:15, name:"Harry" }]

Remove object from array of objects based on object key value

I have an object like
let arr = [
{isManaged: true, id:1},
{isManaged: false, id:2},
{isManaged:false, id:3}
]
to get the values which are true, i do
arr.map(shift => ({
id: shift.id,
isPartnerManaged: shift.isManaged,
}))
but this will only return me the values where i true, now, I want to remove them from the array of objects. I tried to use the array.pop but i don't know what index to feed it. Any ideeas?
arr = arr.filter(shift => shift.isManaged);
You could filter the array and build new objects.
var array = [{ isManaged: true, id: 1 }, { isManaged: false, id: 2 }, { isManaged: false, id: 3 }],
result = array
.filter(({ isManaged }) => isManaged)
.map(({ isManaged: isPartnerManaged, id }) => ({ id, isPartnerManaged }));
console.log(result);

Get array of all unique object values based on property name

How can I get an array with all the unique values based on a property name?
In my case my object looks like this and I want an array with the unique documentID's.
const file = {
invoice: {
invoiceID: 1,
documentID: 5
},
reminders: [
{
reminderID: 1,
documentID: 1
},
{
reminderID: 2,
documentID: 1
}
]
}
The result should be an array [5, 1] //The unique documentID's are 5 and 1
It doesn't seem like possible to add a property name to the Object.values() function.
You can use Set to get unique documentID.
const file = {
invoice: {
invoiceID: 1,
documentID: 5
},
reminders: [
{
reminderID: 1,
documentID: 1
},
{
reminderID: 2,
documentID: 1
}
],
payments: {
documentID : 5
}
};
var keys = Object.keys(file).map(key=>file[key].map ? file[key].map(i=>i.documentID) : file[key].documentID)
var keysFlattened= [].concat.apply([], keys);
var unique = new Set(keysFlattened);
console.log(Array.from(unique));
I use something like this that does what you want I think
const keepUniqueBy = key => (array, item) => {
if (array.find(i => item[key] === i[key])) {
return array;
} else {
return [ ...array, item ];
}
};
Then you can simply: const unique = reminders.reduce(keepUniqueBy('documentID'))
NB: It's probably low performing, but for small arrays it doesn't matter.

ImmutableJS - pushing into a nested array

const List = Immutable.List;
const items = [
{ id: 1, subList: [] },
{ id: 2, subList: [] },
{ id: 3, subList: [] }
];
const newItem = { name: "sublist item" };
let collection = List(items);
collection = collection.updateIn([0, 'subList'], function (items) {
return items.concat(newItem)
});
https://jsbin.com/midimupire/edit?html,js,console
Results in:
Error: invalid keyPath
I think that perhaps I need to set subList as a List(); I get the same error when trying this.
If I understand the question correctly, you want to return collection with the first element as:
{
id : 1,
subList: [
{name: "sublist item"}
]
}
To do this we'll need to make a few changes.
Use Immutable.fromJS to deeply convert the plain JS array of objects to an Immutable List of Maps
Use List.update() to return a new List with the updated value
Use Map.updateIn() to return a new LMapist with the updated value
Here's the whole thing:
const List = Immutable.List;
const items = [{
id: 1,
subList: []
},
{
id: 2,
subList: []
},
{
id: 3,
subList: []
}
];
const newItem = {
name: "sublist item"
};
let collection = Immutable.fromJS(items);
collection = collection.update(0, item => {
return item.updateIn(['subList'], subList => {
return subList.concat(newItem);
});
});
console.log(collection)
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.2/immutable.js"></script>
And the result:
[
{
"id": 1,
"subList": [
{
"name": "sublist item"
}
]
},
{
"id": 2,
"subList": []
},
{
"id": 3,
"subList": []
}
]
Update: List.updateIn() can use an index as the keypath, so you can simplify this to the following:
collection = collection.updateIn([0, 'subList'], subList => {
return subList.concat(newItem);
});
Like this:
const List = Immutable.List;
const items = [{
id: 1,
subList: []
},
{
id: 2,
subList: []
},
{
id: 3,
subList: []
}
];
const newItem = {
name: "sublist item"
};
let collection = Immutable.fromJS(items);
collection = collection.updateIn([0, 'subList'], subList => {
return subList.concat(newItem);
});
console.log(collection)
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.2/immutable.js"></script>
Use the object you got, update the subArray and return the whole object.
const List = Immutable.List;
const items = [
{ id: 1, subList: [] },
{ id: 2, subList: [] },
{id: 3, subList: [] }
];
const newItem = { name: "sublist item" };
let collection = List(items);
collection = collection.update([0], function (obj) {
obj.subList = obj.subList.concat(newItem)
return obj;
});
This doesn’t work because the elements of your Immutable.List are plain-old JavaScript objects (POJO), not Immutable.Maps, so updateIn doesn’t know how to work with them. You can either:
Make the objects Immutable.Maps by using Immutable.fromJS instead of Immutable.List as the constructor to convert the entire object graph to Immutable objects. (See JS Bin)
Use update([0]) instead of updateIn to just get the POJO and mutate it (as in #Navjot’s answer).

Categories

Resources