I'm trying to write a function that iterates through an array of objects, and pushes in new ones (ones that have a unique name), while updating ones that have already been seen.
Say for example, I have this array:
$scope.myArray = [
{ "name": "Apple", "total": 16, "applicable": 21 },
{ "name": "Cherry", "total": 12, "applicable": 27 },
{ "name": "Plum", "total": 14, "applicable": 21 },
{ "name": "Apple", "total": 16, "applicable": 21 },
{ "name": "Cherry", "total": 12, "applicable": 27 },
{ "name": "Plum", "total": 14, "applicable": 21 },
{ "name": "Banana", "total": 14, "applicable": 21 },
];
By the end of the function, the new array should be:
$scope.myNewArray = [
{ "name": "Apple", "total": 32, "applicable": 42},
{ "name": "Cherry", "total": 24, "applicable": 54},
{ "name": "Plum", "total": 28, "applicable": 42},
{ "name": "Banana", "total": 14, "applicable": 21 },
];
Here's what I have so far:
$scope.myArray = [
{ "name": "Apple", "total": 16, "applicable": 21 },
{ "name": "Cherry", "total": 12, "applicable": 27 },
{ "name": "Plum", "total": 14, "applicable": 21 },
{ "name": "Apple", "total": 16, "applicable": 21 },
{ "name": "Cherry", "total": 12, "applicable": 27 },
{ "name": "Plum", "total": 14, "applicable": 21 },
{ "name": "Banana", "total": 14, "applicable": 21 },
];
$scope.myNewArray = [];
$scope.myArray.filter( function () {
var i = $scope.myNewArray.indexOf($scope.myArray.name);
if ($scope.myNewArray.indexOf($scope.myArray.name) < 0)
$scope.myNewArray.push($scope.myArray);
else {
$scope.myNewArray[i].total += $scope.myArray.total;
$scope.myNewArray[i].applicable += $scope.myArray.applicable;
}
});
The problem I'm encountering is everything gets pushed into the new array. That and I believe my else statement where I'm adding the values to the previous record might be wrong.
Also, hard-coding an array for each name doesn't work as this is just a simple example with a small dataset.
Can anyone lend a hand?
try this approach:
create object where keys are name property and total along with applicable are already calculated (Array.prototype.reduce)
Iterate over keys of previously created object and transform it back to array (Object.keys and Array.prototype.map)
var res = {};
res = Object.keys([
{ "name": "Apple", "total": 16, "applicable": 21 },
{ "name": "Cherry", "total": 12, "applicable": 27 },
{ "name": "Plum", "total": 14, "applicable": 21 },
{ "name": "Apple", "total": 16, "applicable": 21 },
{ "name": "Cherry", "total": 12, "applicable": 27 },
{ "name": "Plum", "total": 14, "applicable": 21 },
{ "name": "Banana", "total": 14, "applicable": 21 },
].reduce(function (res, item) {
if (res[item.name]) {
res[item.name].total += item.total;
res[item.name].applicable += item.applicable;
}
else {
res[item.name] = item;
}
return res;
}, res)).map(function(key) {
return res[key];
});
console.log(res);
adding less hardcoded solution:
var myArray = [
{ "name": "Apple", "total": 16, "applicable": 21 },
{ "name": "Cherry", "total": 12, "applicable": 27 },
{ "name": "Plum", "total": 14, "applicable": 21 },
{ "name": "Apple", "total": 16, "applicable": 21 },
{ "name": "Cherry", "total": 12, "applicable": 27 },
{ "name": "Plum", "total": 14, "applicable": 21 },
{ "name": "Banana", "total": 14, "applicable": 21 },
];
var res = {};
// add keys for loopable integers which will be summed
var loopables = Object.keys(myArray[0]).filter(function (key) {
return Number.isInteger(myArray[0][key]);
});
res = Object.keys(myArray.reduce(function (res, item) {
if (res[item.name]) {
loopables.forEach(function (loopableKey) {
res[item.name][loopableKey] += item[loopableKey];
});
}
else {
res[item.name] = item;
}
return res;
}, res)).map(function(key) {
return res[key];
});
console.log(res);
here I only rely on the main key name, the rest integer properties are automatically summed, by iterating over loopables keys array, calculated at the beginning
plunker with Angular: https://plnkr.co/edit/MRr2QRULG8TYs2CqA1By?p=preview
What I do to simply such things is I use angular forEach and in your case, I'd make three different arrays and fill them up with this information. Then I'd use indexof on them and push them to myNewArray. Its easier to work on simple arrays than array objects.
For example on forEach Angular forEach.
I think you can do it in pure javascript
check this following snippet
var obj = [{
"name": "Apple",
"total": 16,
"applicable": 21
}, {
"name": "Cherry",
"total": 12,
"applicable": 27
}, {
"name": "Plum",
"total": 14,
"applicable": 21
}, {
"name": "Apple",
"total": 16,
"applicable": 21
}, {
"name": "Cherry",
"total": 12,
"applicable": 27
}, {
"name": "Plum",
"total": 14,
"applicable": 21
}, {
"name": "Banana",
"total": 14,
"applicable": 21
}, ];
var newObj = [];
MergeObjectProperties(obj);
function MergeObjectProperties(obj) {
Object.keys(obj).forEach(function (key) {
var name = obj[key].name;
var exists = checkProperty(name, newObj)
if (newObj.length == 0 || !exists)
newObj.push(obj[key]);
else {
newObj[exists]["total"] = obj[key].total + newObj[exists]["total"];
newObj[exists]["applicable"] = obj[key].applicable + newObj[exists]["applicable"];
}
});
console.log(newObj);
}
function checkProperty(prop, newObj) {
var result;
Object.keys(newObj).forEach(function (key) {
if (newObj[key]["name"] === prop) {
result = key
}
});
return result;
}
Hope this helps
Related
I have an array :
{
"count": 8,
"id": "accountId",
"name": " Account Id",
"values": [
{
"count": 2,
"id": "1234456789000",
"name": "1234456789000"
},
{
"count": 1,
"id": "135792468045",
"name": "135792468045"
},
{
"count": 1,
"id": "309983110022",
"name": "309983110022"
},
{
"count": 2,
"id": "432112426686",
"name": "432112426686"
},
{
"count": 1,
"id": "6ee26149-a156-4665-bd26-a6e46b49a70f",
"name": "6ee26149-a156-4665-bd26-a6e46b49a70f"
},
{
"count": 1,
"id": "927b48ce-efe4-4c20-98f0-ec6c54f59b45",
"name": "927b48ce-efe4-4c20-98f0-ec6c54f59b45"
}
]
}
And I have a 2nd array :
[
{
"count": 2,
"id": "432112426686",
"name": "432112426686"
},
{
"count": 2,
"id": "1234456789000",
"name": "1234456789000"
}
]
The second array, I have filtered based on some requirement.
I want to replace the values from 1st array with second array.
Using typescript code.
Please help here.
If I understand question, you just need iterate by values array and find same id from second array.
function findAndSwitch(object1, array1): void {
object1.values = object1.values.map(el => {
const objToSwitch = array1.find(eleArr => eleArr.id === el.id);
if (objToSwitch) {
return el = objToSwitch;
} else {
return el;
}
});
}
https://stackblitz.com/edit/typescript-dvty4p
Let's say your variable names are obj1 and arr2, respectively. First transform arr2 into an object obj2:
let obj2 = arr2.reduce((acc,cur) => ({...acc,[cur.id]:cur}),{});
Which now looks like this:
{
'432112426686': {
count: 20,
id: '432112426686',
name: '432112426686'
},
'1234456789000': {
count: 20,
id: '1234456789000',
name: '1234456789000'
}
}
Then transform obj1 based on obj2 as follows:
obj1.values = obj1.values.map(value => obj2[value.id] || value);
Please note that since the data in arr2 is identical to the corresponding data in obj1, I have altered the values of count property in arr2 in order to demonstrate that obj1 will be updated accordingly.
DEMO ONE
let obj1 = {
"count": 8,
"id": "accountId",
"name": " Account Id",
"values": [
{
"count": 2,
"id": "1234456789000",
"name": "1234456789000"
},
{
"count": 1,
"id": "135792468045",
"name": "135792468045"
},
{
"count": 1,
"id": "309983110022",
"name": "309983110022"
},
{
"count": 2,
"id": "432112426686",
"name": "432112426686"
},
{
"count": 1,
"id": "6ee26149-a156-4665-bd26-a6e46b49a70f",
"name": "6ee26149-a156-4665-bd26-a6e46b49a70f"
},
{
"count": 1,
"id": "927b48ce-efe4-4c20-98f0-ec6c54f59b45",
"name": "927b48ce-efe4-4c20-98f0-ec6c54f59b45"
}
]
};
let arr2 = [
{
"count": 20,
"id": "432112426686",
"name": "432112426686"
},
{
"count": 20,
"id": "1234456789000",
"name": "1234456789000"
}
];
let obj2 = arr2.reduce((acc,cur) => ({...acc,[cur.id]:cur}),{});
obj1.values = obj1.values.map(value => obj2[value.id] || value);
console.log( obj1 );
--
However, if all you want is to replace all the obj1.values with arr2, all you need is:
obj1.values = [...arr2];
And this will give rise to:
{
count: 8,
id: 'accountId',
name: ' Account Id',
values: [{
count: 20,
id: '432112426686',
name: '432112426686'
},
{
count: 20,
id: '1234456789000',
name: '1234456789000'
}
]
}
DEMO TWO
let obj1 = {
"count": 8,
"id": "accountId",
"name": " Account Id",
"values": [
{
"count": 2,
"id": "1234456789000",
"name": "1234456789000"
},
{
"count": 1,
"id": "135792468045",
"name": "135792468045"
},
{
"count": 1,
"id": "309983110022",
"name": "309983110022"
},
{
"count": 2,
"id": "432112426686",
"name": "432112426686"
},
{
"count": 1,
"id": "6ee26149-a156-4665-bd26-a6e46b49a70f",
"name": "6ee26149-a156-4665-bd26-a6e46b49a70f"
},
{
"count": 1,
"id": "927b48ce-efe4-4c20-98f0-ec6c54f59b45",
"name": "927b48ce-efe4-4c20-98f0-ec6c54f59b45"
}
]
};
let arr2 = [
{
"count": 20,
"id": "432112426686",
"name": "432112426686"
},
{
"count": 20,
"id": "1234456789000",
"name": "1234456789000"
}
];
obj1.values = arr2;
console.log( obj1 );
When I click a button, I want to get a new list. And the example below
i have this list :
List users = [
{
"id": 31,
"name": "John",
},
{
"id": 23,
"name": "Sami",
},
{
"id": 34,
"name": "Leon",
}
];
when search for id list like [31,34]
i need return this result
List users = [
{
"id": 31,
"name": "John",
},
{
"id": 34,
"name": "Leon",
}
];
You can filter it out like this
var newList = users.where((e) => e['id']==31 || e['id']==34).toList();
here is an example:
List users = [
{
"id": 31,
"name": "John",
},
{
"id": 23,
"name": "Sami",
},
{
"id": 34,
"name": "Leon",
}
];
List<searchIds> = [31, 23];
List<searchUsers> = [];
for (int i = 0; i < searchIds.length; i++) {
searchUsers.add(users.where((x) => x["id"] == searchIds[i]).toList()[0]);
}
I've run into a bit of an interesting situation. I want to remove values from an array of hashes if a specific value in that array is a duplicate. Here's an example of the structure I'm working with:
[
{
"PCDBPart": {
"Category": {
"ID": 22,
"Name": "Wiper and Washer"
}
},
"Position": {
"Name": "Right",
"PCDBPositionID": 12,
"PositionID": 10
}
},
{
"PCDBPart": {
"Category": {
"ID": 22,
"Name": "Wiper and Washer"
}
},
"Position": {
"Name": "Right",
"PCDBPositionID": 12,
"PositionID": 10
}
},
{
"PCDBPart": {
"Category": {
"ID": 24,
"Name": "Wiper and Washer"
}
},
"Position": {
"Name": "Right",
"PCDBPositionID": 2,
"PositionID": 4
}
}
]
The issue I have is that the values in Position are duplicated often, making the array large. I want to return the array with hashes unique by the PositionID they contain.
I tried using my_array.uniq { |h| h.dig(:Position, :PositionID)}, but that just seems to return one value:
[
{
"PCDBPart": {
"Category": {
"ID": 22,
"Name": "Wiper and Washer"
}
},
"Position": {
"Name": "Right",
"PCDBPositionID": 12,
"PositionID": 10
}
},
]
Here's the desired output:
[
{
"PCDBPart": {
"Category": {
"ID": 22,
"Name": "Wiper and Washer"
}
},
"Position": {
"Name": "Right",
"PCDBPositionID": 12,
"PositionID": 10
}
},
{
"PCDBPart": {
"Category": {
"ID": 24,
"Name": "Wiper and Washer"
}
},
"Position": {
"Name": "Right",
"PCDBPositionID": 2,
"PositionID": 4
}
}
]
Does anybody have any suggestions on how to proceed?
I am using Typescript for below problem. I want to search object not simple alphabetic or number in the list.
Below are the two arrays.
I want to get common objects in separate list without using any third party library.
firstArray = [
{
"id": 4,
"name": "Tata"
},
{
"id": 11,
"name": "Maruti"
},
{
"id": 14,
"name": "Mahindra"
}
]
secondArray = [
{
"id": 4,
"name": "Tata"
},
{
"id": 11,
"name": "Maruti"
},
{
"id": 15,
"name": "Hyundai"
},
{
"id": 21,
"name": "Honda"
}
]
// Get Common Elements
// I am getting blank array as output
console.log(firstArray.filter(( make ) => secondArray.includes( make)));
Is there good function or way to find out commons element?
You can use array#filter with array#some. For each object in the first array, check if id and name exist in the other array.
const firstArray = [{ "id": 4, "name": "Tata" }, { "id": 11, "name": "Maruti" }, { "id": 14, "name": "Mahindra" } ],
secondArray = [{ "id": 4, "name": "Tata" }, { "id": 11, "name": "Maruti" }, { "id": 15, "name": "Hyundai" }, { "id": 21, "name": "Honda" } ],
result = firstArray.filter(o => secondArray.some(({id,name}) => o.id === id && o.name === name));
console.log(result);
For ES6, you can also try sets,
For demonstration,
const thirdArray = [...new Set([...firstArray ,...secondArray])];
I'm basically trying to do what is done with this question, but with an array and return all objects using the values of the corresponding array, not just the value:
Filter backbone collection by attribute value
My natural instinct is to use _.filter or _.partition on the persons collection, but am confused on how these are being compared & returned and am not getting the desired outcome.
With the following, passing the id in via the router:
friendsRoute: function(id){
persons = new App.Collections.Persons();
persons.fetch().done(function(){
var single = persons.find(function(i){
return i.get('id') == id;
});
var friendsIds = single.get('friends');
var friends = ?
//var friendsList = new App.Views.FriendsList();
//friendsList.render({ friends: friends });
});
},
I have a friendsIds array (Joe's friends):
friendsIds = [1,4,5]
And trying to get the matched ids from the following JSON and display their names in my friendsList view:
[
{ "id": 1, "name": "Steve", "age": 22, "friends": [4] },
{ "id": 2, "name": "Mary", "age": 18, "friends": [1,3] },
{ "id": 3, "name": "Joe", "age": 43, "friends": [1,4,5] },
{ "id": 4, "name": "Tommy", "age": 19, "friends": [1] },
{ "id": 5, "name": "Leslie", "age": 27, "friends": [2,4] }
]
I think you could use a combination of map and findWhere to do this:
var friends = _.map(friendsIds, function(id) {
return _.findWhere(persons, { 'id': id });
});
var friendsIds = [1,4,5];
var friends = [
{ "id": 1, "name": "Steve", "age": 22, "friends": [4] },
{ "id": 2, "name": "Mary", "age": 18, "friends": [1,3] },
{ "id": 3, "name": "Joe", "age": 43, "friends": [1,4,5] },
{ "id": 4, "name": "Tommy", "age": 19, "friends": [1] },
{ "id": 5, "name": "Leslie", "age": 27, "friends": [2,4] }
];
var filteredFriends = _.filter(friends, function(frnd){
return _.contains(friendsIds, frnd.id);
});
console.log(filteredFriends);
See the difference in performance with filter and map here
Make use of filter and contains
FIDDLE