how to check object name? - javascript

I have object and this object include objects too. It looks like:
$scope.data = {
tree : {
name : 'oak',
old : 54
},
dog : {
name : 'Lucky',
old : 3
},
system1 : {
name : '',
old : ''
},
baby : {
name : 'Jack',
old : 1
},
cat : {
name : 'Fluffy',
old : 2
},
system2 : {
name : '-',
old : '-'
}
}
As you can see this objects has obj name like - tree, dog, system etc. And I want to take only objects with name system, but this name can changes like system1, system123, system8. So I try to use this reg exp for ignore numbers
replace(/\d+/g, '')
But I can't reach this object name. I try this:
angular.forEach($scope.data, function(item){conole.log(item)}) // but it shows content in obj not obj name..
How can I reach this obj name and distinguish this 2 system objects?

var data = {
tree : {
name : 'oak',
old : 54
},
dog : {
name : 'Lucky',
old : 3
},
system1 : {
name : '',
old : ''
},
baby : {
name : 'Jack',
old : 1
},
cat : {
name : 'Fluffy',
old : 2
},
system2 : {
name : '-',
old : '-'
}
}
data = Object.keys(data) // get keys
.filter(key => key.startsWith('system')) // filter keys starting with system
.map(key => data[key]) // map to the values, returning a new array
console.log(data) // and you have you array with systems

Pass another param to the function like key to the forEach callBack Function. It is the key of the each object inside the object in your use-case.
Check the below example
var items = {
car: {
a: 123
},
dog: {
b: 234
},
system: {
c: 456
}
};
angular.forEach(items, function(item, key) {
console.log(key);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

You can use Object.keys(myObject), that return an array of all the keys of the passed object, for istance:
var myObject= {
cat : {
name : 'Fluffy',
old : 2
},
system2 : {
name : '-',
old : '-'
}
}
var keys = Object.keys(myObject); // Keys will be ['cat', 'system2']
Cheers

You have to pass another parameter to angular foreach function to get the key name of the object like this:-
angular.forEach($scope.data, function(item, key){ // Here key is the keyname of the object
console.log(item, key);
});

Related

How can I remove duplicates in an array of object?

I have an array which looks like this :
var array =
[
{
key : { id : 1 , pack : "pack 1"},
values : [
{
item : { id : 1 , name : "item1"},
itemP : {id : 2 , name : "itemP12"}
},
{
item : { id : 4 , name : "item4"},
itemP : {id : 2 , name : "itemP12"}
},
]
}
]
I want to remove duplicate itemP so with a function it will look like this :
var array =
[
{
key : { id : 1 , pack : "pack 1"},
values : [
{
item : { id : 1 , name : "item1"},
itemP : {id : 2 , name : "itemP12"}
},
{
item : { id : 4 , name : "item4"},
itemP : null
},
]
}
]
When I try I always have errors. It is possible to do this?
Update
I try to do this :
console.log(array.map(pack =>
pack.values.map((item) => {
var test = JSON.stringify(item)
var set = new Set(test)
return Array.from(set).map((item)=> JSON.parse(item))
}
)
))
Unexpected end of JSON input
I also try something will filter but it doesn't work:
console.log(this.package.map(pack => pack.values.filter(
(value, index , array) => array.itemP.indexOf(value) === index
)))
Instead of mapping every key property, I suggest cloning the whole structure and setting the object value as null in the cloned one, avoiding unintentionally mutating the original structure.
function nullifyDupes(array) {
const clone = JSON.parse(JSON.stringify(array));
const seen = {};
clone.forEach(pack => {
pack.values.forEach(items => {
for (const item in items) {
const id = items[item].id;
if (seen[id]) items[item] = null;
else seen[id] = true;
}
});
});
return clone;
}
const originalArray = [{
key : { id : 1 , pack : "pack 1"},
values : [{
item : { id : 1 , name : "item1"},
itemP : {id : 2 , name : "itemP12"}
},
{
item : { id : 4 , name : "item4"},
itemP : {id : 2 , name : "itemP12"}
}]
}];
const mutatedArray = nullifyDupes(originalArray);
console.log(mutatedArray);
To achieve expected result, use below option of using map
Loop array using map
Use nameArr to check duplicate and assigning null value
Loop values array and check the name in nameArr using indexOf and assign null
var array = [
{
key : { id : 1 , pack : "pack 1"},
values : [
{
item : { id : 1 , name : "item1"},
itemP : {id : 2 , name : "itemP12"}
},
{
item : { id : 4 , name : "item4"},
itemP : {id : 2 , name : "itemP12"}
}
]
}
]
console.log(array.map(v => {
let nameArr = []
v.values = v.values.map(val => {
if(nameArr.indexOf(val.itemP.name) !== -1){
val.itemP.name = null
}else{
nameArr.push(val.itemP.name)
}
return val
})
return v
}))
You can use map and an object to check if its already exist. Like
var obj = {}
and loop over values
var values = [
{
item : { id : 1 , name : "item1"},
itemP : {id : 2 , name : "itemP12"}
},
{
item : { id : 4 , name : "item4"},
itemP : {id : 2 , name : "itemP12"}
}
]
values.map((v) => {
if(!obj[v.itemP.id + '-' + v.itemP.name]) {
obj[v.itemP.id + '-' + v.itemP.name] = true;
return v;
}
return { item : v.item }
})
You can map your array elements to array objects which don't include your duplicates using .map(). For each iteration of .map() you can again use .map() for your inner values array to convert it into an array of objects such that the duplicates are converted to null. Here I have kept a seen object which keeps track of the properties seen and their stringified values. By looping over all the properties in your object (using for...of), you can work out whether or not the key-value pair has been seen before by using the seen object.
The advantage of this approach is that it doesn't just work with one property (ie not just itemP), but it will work with any other duplicating key-value pairs.
See example below:
const array = [{key:{id:1,pack:"pack 1"},values:[{item:{id:1,name:"item1"},itemP:{id:2,name:"itemP12"}},{item:{id:4,name:"item4"},itemP:{id:2,name:"itemP12"}}]}];
const seen = {};
const res = array.map(obj => {
obj.values = obj.values.map(vobj => {
for (let p in vobj) {
vobj[p] = seen[p] === JSON.stringify(vobj[p]) ? null : vobj[p];
seen[p] = seen[p] || JSON.stringify(vobj[p]);
}
return vobj;
});
return obj;
});
console.log(res);
For an approach which just removed itemP from all object in accross your array you can use:
const array = [{key:{id:1,pack:"pack 1"},values:[{item:{id:1,name:"item1"},itemP:{id:2,name:"itemP12"}},{item:{id:4,name:"item4"},itemP:{id:2,name:"itemP12"}}]}];
let itemP = "";
const res = array.map(obj => {
obj.values = obj.values.map(vobj => {
vobj.itemP = itemP ? null : vobj.itemP;
if('itemP' in vobj) {
itemP = itemP || JSON.stringify(vobj.itemP);
}
return vobj;
});
return obj;
});
console.log(res);

How to push object in array with those records in object should not reside under object name?

I am trying to push data in array but I don't want that data to come under any object.
Expected output:
name : "abc"
array1 : [],
flag : false
myObj1 : {}
myObj2 : {}
But I am getting data in arr variable in array like below:
myObj :
name : "abc"
array1 : [],
flag : false
myObj1 : {}
myObj2 : {}
Code:
var arr = [];
function pushData(myObj)
{
arr.push(
{
myObj
myObj1 : { title: myObj.name, flag: true, value: 0 },
myObj2: { location : null,age : 10 }
//some other objects which I want to initialize here only
}
);
}
Is this possible to get expected output in arr variable?
I think you want to assign Object1 and 2 to Object:
arr.push(Object.assign({},myObj,{
myObj1 : { title: myObj.name, flag: true, value: 0 },
myObj2: { location : null,age : 10 }
}));
Will create this:
[{
name : "abc"
array1 : [],
flag : false
myObj1 : {title,flag,value}
myObj2 : {location,age}
}];
If you're transpiling your code with Babel for ES6 capabilities, you can use object spread properties:
var arr = [];
function pushData(myObj) {
arr.push({
...myObj,
myObj1: {},
myObj2: {}
});
}
pushData({ name: "abc", array1: [], flag: false });
console.log(arr);
Here's the current compatibility stats.

Removing duplicates from an array of objects

I have an object which has json objects called
mainobject =
Array[2]
>0: object
>Innerobject1 : Array[2]
>0 : object
Name : "Xavier"
Dup : "B"
>1 : object
Name : "Gh"
Dup : "B"
>1: object
>Innerobject2 : Array[2]
>0 : object
Name : "Cat"
Dup : "C"
>1 : object
Name : "Dog"
Dup : "D"
I need to make the "dup" as "" which was already present in the first object if any .My expected output is:
Array[2]
>0: object
>Innerobject1 : Array[2]
>0 : object
Name : "Xavier"
Dup : "B"
>1 : object
Name : "Gh"
Dup : ""
>1: object
>Innerobject2 : Array[2]
>0 : object
Name : "Cat"
Dup : "C"
>1 : object
Name : "Dog"
Dup : "D"
Edit:
The object in json format:
:
"[{"Innerobject1":[{"Name" :"Xavier","Dup":"B"},{"Name" :"Gh","Dup":"B"}]},
{"Innerobject2":[{"Name" : "Cat","Dup":"C"},{"Name":"Dog", "Dup":"D"}]}]"
I'm not quite sure that I have interpreted your posted array of objects correct. But you can do something like this:
Iterate over the array and store the key you want to be unique in an object. When encountered more then once set the new value to an empty string:
var seen = {};
mainobject.forEach(function(obj) {
if (seen[obj.Name]) {
obj.Name = "";
}
seen[obj.Name] = true;
});
You might need multiply iterations, dependents on how many nested arrays you got:
var seen = {};
mainobject.forEach(function(inner_arr) {
inner_arr.forEach(function(obj) {
if (seen[obj.Name]) {
obj.Name = "";
}
seen[obj.Name] = true;
});
});
The solution using Array.forEach and Object.keys functions:
var mainobject = JSON.parse('[{"Innerobject1":[{"Name" :"Xavier","Dup":"B"},{"Name" :"Gh","Dup":"B"}]},{"Innerobject2":[{"Name" : "Cat","Dup":"C"},{"Name":"Dog", "Dup":"D"}]}]');
mainobject.forEach(function(obj){
Object.keys(obj).forEach(function(k){
obj[k].forEach(function(o){
if (this["Dup"]) {
(this["Dup"].indexOf(o["Dup"]) !== -1)? o["Dup"] = "" : this["Dup"].push(o["Dup"]);
} else {
this["Dup"] = [o["Dup"]];
}
})
});
}, {});
console.log(JSON.stringify(mainobject, 0, 4));
The console.log output:
[
{
"Innerobject1": [
{
"Name": "Xavier",
"Dup": "B"
},
{
"Name": "Gh",
"Dup": ""
}
]
},
{
"Innerobject2": [
{
"Name": "Cat",
"Dup": "C"
},
{
"Name": "Dog",
"Dup": "D"
}
]
}
]

JavaScript Deleting all objects from an array which contain a value

I have an obj, with an array of objects - something like below (I've not pasted it here because its HUGE). I'm trying to loop through the array of objects - deleting those objects from the array which contain a value. I have written the following code... (using lodash)
When looping over the array its randomly missing a few 'Foo's - so not all the Foo objects are deleted... even though they contain the key Foo. It does ignore that which doesn't contain Foo though.
obj = {
array : [
{
key1 : 'Foo',
Key2 : 'fi'
},
{
key1 : 'Foo',
Key2 : 'fi',
Key3 : 'blah'
},
{
key1 : 'Fred',
Key2 : 'fi'
},
{
key1 : 'Foo',
Key2 : 'fi'
}
... etc....
]
}
var items = obj.array
_.forEach(items, function(n, index) {
var isFoo = _.includes(n, 'Foo');
console.log(isFoo);
if (isFoo) {
items.splice(index, 1);
}
});
I suspect things are getting confused because you are changing the array at the same time as you are looping through it.
_.remove is probably a better option for you here:
var obj = {
array : [
{
key1 : 'Foo',
Key2 : 'fi'
},
{
key1 : 'Foo',
Key2 : 'fi',
Key3 : 'blah'
},
{
key1 : 'Fred',
Key2 : 'fi'
},
{
key1 : 'Foo',
Key2 : 'fi'
}
]
};
_.remove(obj.array, function(n, index) {
return _.includes(n, 'Foo');
});
console.dir(obj.array)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.0/lodash.js"></script>
I ditched lodash, and just did a reverse for-loop (my thinking was that as things were being removed, the index would change... and maybe that was causing the errors?)
var items = obj.array;
var i;
for (i = items.length - 1; i >= 0; i -= 1) {
if (items[i].type === 'Foo') {
items.splice(i, 1);
}
}

Compare array and remove unmatched values

$scope.locations = [
{ name : "One"},
{ name : "Two"},
{ name : "Three"},
{ name : "India"},
{ name : "Japan"},
{ name : "China"}
];
$scope.tempLocations = [
{ name : "One"},
{ name : "Two"},
{ name : "global"},
];
I have two arrays. If location doesn't contain some of the names in tempLocations I want to remove them from tempLocation. In this case i want to remove location Global
I tried the following, but does not work.
for(var i=0;i<$scope.tempLocations.length;i++){
var index = $scope.tempLocations.indexOf($scope.locations[i]);
if(index == -1){
console.log($scope.tempLocations[i]);
$scope.tempLocations.splice(i,1);
}
}
I guess you're looking for this
$scope = {}
$scope.locations = [
{ name : "One"},
{ name : "Two"},
{ name : "Three"},
{ name : "India"},
{ name : "Japan"},
{ name : "China"}
];
$scope.tempLocations = [
{ name : "One"},
{ name : "Two"},
{ name : "global"},
];
$scope.tempLocations = $scope.tempLocations.filter(function(x) {
return $scope.locations.some(function(y) {
return x.name == y.name
})
})
document.getElementById("output").innerHTML = JSON.stringify($scope.tempLocations, 0,' ');
console.log($scope);
<pre id="output"></pre>
If you have many (100+) locations, consider converting them to an "associative array" first, like:
validLocations = { "One": 1, "Two": 1 ... etc
You need to loop through manually as the comment from Paul S. suggests:
var locations = [
{ name : "One"},
{ name : "Two"},
{ name : "Three"},
{ name : "India"},
{ name : "Japan"},
{ name : "China"} ];
var tempLocations = [
{ name : "One"},
{ name : "Two"},
{ name : "global"},
];
var newTempLocations = tempLocations.filter(function(temp){
return locations.some(function(location){ // stop and return true at first match
return location.name === temp.name;
});
})
// print output
document.getElementById("output").innerHTML = JSON.stringify(newTempLocations, null, " ");
<pre id="output"></pre>
If $scope.locations isn't going to change often, you could do the following:
Build a lookup table for locations
var location_lookup = {};
for ( var i = 0; i < $scope.locations.length; i++ ) {
location_lookup[$scope.locations[i].name] = true;
}
Filter based on the existence of a key
$scope.filteredLocations = $scope.tempLocations.filter(function(temp) {
return location_lookup.hasOwnProperty(temp.name);
});
This will prove to be much faster if you're filtering more often than you need to recompute the lookup. So if $scope.locations is static, this would be a good route.
I would advise against using temp.name in location_lookup as another poster said to since that will also check ALL of the prototyped properties of the location_lookup object. For instance, if another script in your app did Object.prototype.global = function(){} then the filter would return "global" as being part of $scope.locations, which is not the behavior you want. hasOwnProperty will only check the object itself and not any prototypical inheritance while also being a more efficient method.
Fiddle Demonstration: http://jsfiddle.net/cu33ojfy/ (also included an implementation that uses Array.prototype to add a .filter_locations() method, but adding to Array.prototype is generally a bad idea)

Categories