Extracting multiple object values - javascript

I have an object like this:
object["key1"] = "text1"
object["key2"] = "text2"
object["key3"] = "text1"
object["key4"] = "text3"
How can I give out (e.g. alert) the elements with the same values (text1, text2 and so on)?
In the above example it should be object["key1"] and object["key2"].
Thanks

You could "invert" your object (properties become values, values become properties):
var byValue = {};
for (var prop in object) {
if (!(object[prop] in byValue)) {
byValue[object[prop]] = [];
}
byValue[object[prop]].push(prop);
}
This should yield this structure:
{
'text1': ['key1', 'key3'],
'text2': ['key2'],
'text3': ['key4']
}
Then, you can detect those values that had duplicate keys:
for (var value in byValue) {
if (byValue[value].length > 1) {
alert(byValue[value].join(', '));
}
}

I have sorted the array and then considered that you would want to alert,or do any
functionality, only once for every repeated element.
WARNING: Sorting can get heavy with the size of the array
http://jsfiddle.net/SPQJ7/
The above fiddle is already setup and working with multiple reapeated elements

I updated my script
http://jsfiddle.net/HerrSerker/LAnRt/
This does not check for identity in complex values, just for equality (see foo example)

Related

Adding two same rows in array than modifying only one of them

First, I am adding two same rows in array and later I need to modify only the last one, adding new property to it. The way I do that:
for(var index in arrayOne) {
var arrayOneItem = arrayOne[index];
var new_row = {
address: arrayOne[index].address,
date: arrayOne[index].date,
category: arrayOne[index].category,
};
rows.push(new_row);
if(arrayOne[index].refund_status == 'refunded') {
rows.push(new_row);
rows[rows.length - 1].refund_status = 'refunded';
}
}
But the problem is that the code inside if statement does not only modify last row, but also the one before it, so the refund_status = 'refunded' is added both to the last and one before last row. Why is this happening and is there a way to modify the last row only?
When you are using the same object twice it's best to create a copy (shallow in this case) using Object.assign(). This will avoid referencing the same object from multiple variables or array indexes in your case.
eg.
rows.push(new_row);
becomes
rows.push(Object.assign({}, new_row));
This is because the object you push into the array is passed by reference and not by value, thus when you change the original object you will change both references to it in the array, see example below:
let someArray = [];
let someObj = {foo: "bar"};
someArray.push(someObj);
someArray.push(someObj);
someArray[0].foo = "baz";
console.log(someArray[1]);
To avoid this, you would need to clone the values of the object to create a new one. This question has some ways to do so, using JSON.parse and JSON.stringify is the shortest way to deep-copy an object without an external library, see example below:
let someArray = [];
let someObj = {foo: "bar"};
someArray.push(someObj);
let newObj = JSON.parse(JSON.stringify(someObj));
someArray.push(newObj);
someArray[0].foo = "baz";
console.log(someArray[1]);
Because you are changing property of an object, and object in javaScript is accessed through a link not a separate instance. In another words, you have the same object in memory and you change its property. It means, new_row is object you create and push it several times, and it's the same.
You can avoid it by copying it when pushing second times:
if(arrayOne[index].refund_status == 'refunded') {
rows.push({ ...new_row });
rows[rows.length - 1].refund_status = 'refunded';
}
where { ...new_row } basically creates new copy.
When you do rows[rows.length - 1].refund_status = 'refunded'; only second last will change.
Another solution i'd suggest is a bit more accurate:
const rows = []; // empty
const arrayOne = []; // SOME DATA HERE as I understand
const refundedStatus = ;
arrayOne.forEach(element=> {
rows.push(element);
if (value.refund_status === 'refunded') {
rows[rows.length].refund_status = 'refunded';
rows.push({ ...element});
}
});

javascript get second variable from array

I have javascript that is checking multiple fields in Dynamics CRM. If some of them or all are "1" it will use the highest value to use in a calculation.
I pasted a part of the script:
var level1 = {
percentage: 0,
label: "MyLabel"
}
var level2 = {
percentage: 0,
label: "MySecondLabel"
}
if (Xrm.Page.getAttribute("conditioninterested").getValue() == 1) {
level1[0] = 50;
}
if (Xrm.Page.getAttribute("revenueconditionquote").getValue() == 1) {
level2[0] = 70;
}
var chance = Math.max(level1[0],level2[0]);
How do I get the corresponding label after the Math.max found out the percentage to use?
With the way your data is structured I would add the level objects to an array and then filter by chance. filter returns an array so you need to take the first element [0] which is an object, and then the label value from that object.
var label = [level1, level2].filter(function (el) {
return el[0] === chance;
})[0].label; // MySecondLabel
DEMO
First of all, you are could have made a constructor function to declare the object instances, secondly level1 and level2 are objects, So basically there are two ways you can access object properties:
Dot notation, eg. level1.lebel or level1.percentage
the [] notation. You need to put the key in, not the index number. Objects don't have indexes, they are key and value pairs. and also they are un-ordered.

Named objects and collection of them

not sure how to ask tbh :)
I'm used of PHP's associative arrays so much that I struggle to understand how to create an "named array" of objects.
Example:
I have two arrays, two ints and one boolean. This represents one of my entities. I have multiple entities on which I'm doing some work.
In PHP I would write:
$entitites[$entitity_id]['items'][] = $item;
$entitites[$entitity_id]['items_status'][] = $item_status;
$entitites[$entitity_id]['items_count']++;
and so on..
How do I do this with objects in JS?
var entities = {items:[], items_status: [], items_count: 0};
entities[entity_id].items.push(item)
How does one name his object for later access (via name or in my case, entity_id?)
This code doesnt work for me to this extend that my webpage goes blank without any errors produced :S
I also tried this:
var entities = {};
var entity = {items:[], items_status: [], items_count: 0};
but then I dont know how to always add values to already existing object in entities object and how to call that exact object via name eg. entity_id.
Halp :(
Keep entities as an object. Then you can just go ahead and add each entity_id as a key and an object which has all the details of that entity as the value.
var entities = {};
entities["1234"] = {
"items" : [],
"items_status" : [],
"items_count" : 0
};
There are 2 types involved here: Objects & Arrays.
Arrays are simple and you're probably familiar with them from any other language:
var myArray = []; // this is an empty array
myArray[0] = 1;
myArray[1] = 2;
myArray[2] = 3;
// you could also use "var myArray = [1, 2, 3];" instead
alert(myArray[1]); // alerts the value 2
Note: arrays are actually objects, and can have non-index properties as well
You can also use various array functions such as .push(), .pop(), .shift() and so on to mutate the array instead.
Objects share the square brackets notation, but the purpose is different:
var myObject = {}; // this is an empty object
myObject[0] = 1;
myObject[1] = 2;
myObject[2] = 3;
alert(myObject[1]); // alerts the value 2
// but also...
myObject['prop'] = 4;
alert(myObject['prop']); // alerts the value 4
// and
myObject.prop2 = 5;
alert(myObject.prop2); // alerts the value 5
// and lastly
alert(myObject.prop); // alerts the value 4
So while arrays are accessed by index, objects are accessed by property names.
As for your entities, it looks like an array of objects. Lets see how we can do that:
function Entity() {
this.items = [];
this.items_status = [];
this.items_count = 0;
}
var entitites = [];
entities.push(new Entity());
entities[0].items = [1, 2, 3];
entities[0].items_status = ['good', 'good', 'poor'];
entities[0].items_count = 3;
Or you can wrap insertion in a more elegant function:
Entity.prototype.insert(item, status) {
this.items.push(item);
this.items_status.push(status);
this.items_count++;
}
entities[0].insert(4, 'excellent!');
If you want to keep control of the indexes in your JS array you can do so by not using .push() :
var entities = [];
entities[5] = {items:[], items_status:[], items_count:0};
Just replace 5 by your integer entity_id variable, and there you go.
You can use a regular javascript object to create the associative array you're looking for.
Actually it's PHP's implementation that's abit off but all they do is call it different (associative array) to most other language that simply refer to it as an object or hash.
You can use numeric keys in JS and still access them with the [] square brackets.
It works like this:
var my_obj = {};
my_obj[5] = 'any value';
console.log(my_obj); // {5: 'any value'}
JS will not add any redundant undefined to missing indexes either so when looping over the collection you won't loop over undefined.
Also, I can access the object by using the key as a string or as number so you won't have to check if the key is the right type. Taken from the above example:
console.log(my_obj['5']); // 'any value'
console.log(my_obj[5]); // 'any value'
JS Objects are the equivelant of PHP assoc arrays except JS objects are much more flexible than PHP's associative arrays.
The only downside to this is that you can't have duplicate keys.
No two keys may exist that share the same name, in an array if you .push(an_item) it will create a new index making even a duplicate data entry unique but when overwriting a key with a new value only the last value will persist, mind that :)

Removing an object from a javascript list of objects

I currently have a list of objects in javascript indexed by a key:
var list = [];
list['a'] = [];
list['a'].push({obj: 'test'});
list['a'].push({obj: 'test2'});
list['b'] = [];
list['b'].push({obj: 'test'});
list['b'].push({obj: 'test2'});
I would list to remove the entry based on the key (a/b)
I have tried the following:
for(var x in list) { delete list[x]; }
that works but it actually leaves an undefined entry in the list.
I have also tried splicing the array, but that does not seems to work in this case.
Any thoughts on how to remove the entry in javascript or jQuery?
Thanks.
The Fix:
After reading some of the comments, i was able to better understand what my list is consistent of. Therefor, i was able to do the removal by doing the following:
delete list.b;
I'm not sure if my list is best way to organize my structure, but doing a delete on the list and treating it like an object property did the trick.
Thanks for all the feedback.
I'll assume list is an object, not an array.
If you want to reset a or (or b it's done the same way)
list.a.length = 0;
If you want to delete an element from a at a known index (let index)
list.a.splice(index, 1);
You're attempting to add the elements to the array object as object properties and not as array elements. You can verify this by inspecting the value of list.length (will be 0).
So when doing something such as the following:
function removeProperty(id) {
if (list.hasOwnProperty(id)) {
delete list[id];
}
}
removeProperty('a');
it's really the same as:
delete list.a;
which is why you think it leaves an undefined 'entry' in the 'list'.
You'll need to use a literal object instead:
var list = {};
list['a'] = [];
...
list['b' = [];
...
which would allow you to use delete and have it behave as you expect. Of course you'll lose the .length property on the array but you never had that anyway.
Create a simple prototype for the Array class
Array.prototype.remove = function() {
// Helper function to remove a single element from a list if exists
item = arguments[0]
if (this.includes(item)) {
index = this.indexOf(item)
this.splice(index, 1)
}
}
// Now we can call
myList.remove(YourObject)
The above code will add the remove method to all your lists, so this will help you not just for objects but also strings, integers, or any data type
var list = {1: [{},{}], 2: [{},{}]};
function removeProperty(obj, prop){
if(obj[prop]){
delete obj[prop];
}
}
removeProperty(list,"1");
console.log(list);
If this quote:
I would list to remove the entry based on the key (a/b)
means you would like to select the list to consider based off the key (a/b), then remove elements in the list (or all of them), you can try this:
var list = [];
list['a'] = [];
list['a'].push({obj: 'test4'});
list['a'].push({obj: 'test5'});
list['b'] = [];
list['b'].push({obj: 'test'});
list['b'].push({obj: 'test2'});
var toRemove = 'test4';
var removeFrom = "a";
var consideredList;
for (var prop in list) {
if (prop == removeFrom) {
consideredList = list[prop];
}
}
//Remove everything from the considered list
consideredList.splice(0, consideredList.length);
//Remove based off value, if you know the property name
// for(var pos in consideredList) {
// if(consideredList[pos].obj == toRemove) {
// consideredList.splice(pos, 1);
// }
// }
I made a Plunker of a few different cases (check the script.js file). There seems to be a bit of confusion on what you are after and hopefully this is helpful to you somehow. Good luck.

Getting Length of Object in Javascript / jQuery

I am trying to set up an array in jQuery and I then need to do a for loop on it. But it seems that I cant use an associative array for some reason?
var items = new Array();
items['foo'] = 123456;
items['bar'] = 789012;
items['baz'] = 345678;
items['bat'] = 901234;
alert(items.length);
This is just a test, but it return 0?
You can't make associative array in JavaScript like what you want, instead you can use Object.
For example:
var items = {
foo : 123456,
bar : 789012,
baz : 345678,
bat : 901234
}
And to calculate the length you can do:
var getObjectSize = function(obj) {
var len = 0, key;
for (key in obj) {
if (obj.hasOwnProperty(key)) len++;
}
return len;
};
Use: getObjectSize(items); // output: 4
For more see here.
Another one is:
Object.keys(items).length;
But not supported by all browsers.
var items = new Array();
items['foo'] = 123456;
The problem lies in the very first line. You believe that you are adding an item to the array at the index foo, but you are actually adding a property to the items variable with a key foo and value 123456. If you were to type items.foo it would give you back your 123456.
The problem with this approach is that adding a property to an array does not magically increase it's length.
If you want to have non-numeric indexes, you need to use an object instead of an array:
var items = {
foo: 123456,
bar: 789012,
baz: 345678,
bat: 901234
};
Another approach might be to set up two different arrays, which you construct in parallel:
var items = [], items2 = [];
items.push('foo');
items2.push(123456);
// etc.
alert(items2.length);​
The efficiency of this approach depends on how you'll use it. If you're only going to loop through the list of items and do something to each of them, this approach may be more efficient. But if you need to use it like an associative array (items['foo']), then you're better off building an object.
The .length property returns the highest numerical index of the array. Thus, in your case, there is no numerical index and it returns 0. Try
items[98] = "something";
items.length will be 98..! Use the .length property with caution, and if you also want to count the non-numerical indici, loop over the Object (an Array is also an Object) and count its ownProperties.

Categories

Resources