Assigning Unordered keys to a Js array - javascript

I am getting a random key value pair,Can i assign it to an array?
Its problematic here when I assign it like arr[50] = 'abc' it automatically creates the keys upto 50 like arr[0],arr[1],arr[2] and so on.
and i wanted an array like this arr[50=>'abc','40'=>'pqr','53'=>'lmn']
I have it here
if(typeof(feedArr.latestRating) == 'object'){
jQuery.each(feedArr.latestRating,function(key,val){alert('key::'+key);
if(key in newRatingArr){
//delete the key if already exists
newRatingArr.splice(key,1);
}else{
//insert the key,value
newRatingArr[key] = val; //here is the problem occurs when key is 50 it automatically creates the indexes in the array upto 50 which i dont want
// alert('Key between::'+key);
// alert('Value between::'+newRatingArr[key]);
//newRatingArr.splice(key,0,val);
}
//alert(key);
emptyRate = 0;
});
}else{
emptyRate = 1;
}
What can i do here?Please let me know.

Use an object {} instead of an array [].
Objects can act as unordered key-value containers, which is what you seem to be needing here.
// somewhere...
var newRatingArr = {};
// your code.
var emptyRate = true;
if (typeof (feedArr.latestRating) == 'object') {
jQuery.each(feedArr.latestRating, function (key, val) {
newRatingArr[key] = val;
emptyRate = false;
});
}

Related

Create array of objects based off the same property names

I have form inputs that are generated based off an XML file.
We keep a reference of nested elements in the XML file via data-* attributes which can later be used to build an object. For example:
<parent>
<child>
<grandchild1>first</grandchild1>
<grandchild2>second</grandchild2>
</child>
</parent>
Becomes
<input type="text" data-nest="parent.child.grandchild1" value="first"/>
<input type="text" data-nest="parent.child.grandchild2" value="second"/>
When we submit the form, I create an object (with nested objects) based off of their data-nest attribute. The above would become
parent:{
child:{
grandchild1: first,
grandchild2: second
}
}
The issue that I am running into is where multiple of the same tag are found in the XML file, e.g.
<child>
<grandchild>first</grandchild>
<grandchildFriend>firstFriend</grandchildFriend>
</child>
<child>
<grandchild>second</grandchild>
<grandchildFriend>secondFriend</grandchildFriend>
</child>
When I create my object, I would like it so that if multiple occurrences of the same data-nest value are found, they are nested inside of an array in order to maintain the different values.
With the current setup, the second occurrence of the tag will understandably overwrite the first.
This is the final object structure I desire:
parent:{
child:[
{
grandchild: first,
grandchildFriend: firstFriend
},
{
grandchild: second,
grandchildFriend: secondFriend
}
]
}
TL;DR
I'd like to change an object to an array of nested objects if they have the same data-* attribute
Here's a fiddle of how the current code works to help give a better understanding.
replacing currentObj[lastKey] = value; with this:
if(typeof currentObj[lastKey] === 'undefined') {
currentObj[lastKey] = value;
} else {
if(typeof currentObj[lastKey] !== 'array')
currentObj[lastKey] = [currentObj[lastKey]];
currentObj[lastKey].push(value);
}
the code will do the following: if currentObj[lastKey] is not set, you will create an element as always, otherwise, if it is already set and is a string the code will convert it into an array and then push into the arrays the subsequent (as many as you want) elements
and the final result will be something similar to:
parent:{
...
grandchild:[
"first", "second"
]
...
}
Edit
in order to have a result in the format that you have requested, you need to do some more edit, like following:
var json = {};
config = {
set: function(keyValueString) {
var pair = keyValueString.split('=');
// left of the = is the key path
var keyPath = pair[0];
// right of the = is the value to set
var value = pair[1];
// split keyPath into an array of keys
var keys = keyPath.split('.');
var key;
var currentObj = json;
// loop through all keys in the key path, except the last one.
// this creates the object structure implied by the key path.
// we want to do something different on the last iteration.
for (var i=0; i < keys.length-1; i++) {
// Get the current key we are looping
key = keys[i];
// if the requested level on the current object doesn't exist,
// make a blank object.
if (typeof currentObj[key] === 'undefined') {
currentObj[key] = i === keys.length-2 ? []: {};
}
currentObj = currentObj[key];
}
// our loop doesn't handle the last key, because that's when we
// want to set the actual value.
var lastKey = keys[keys.length-1]
// set the property of the deepest object to the value.
var child = {};
child[lastKey] = value;
currentObj.push(child);
}
};
// iterate through all of our inputs, and nest them based off their data-* attribute
$('input').each(function(){
// set nest = value setup, e.g. parent.child.grandchild = first
// we then break this
var key = $(this).attr('data-nest') + '=' + $(this).val();
config.set(key);
});
// as a bonus - this is how I went about breaking multiple values within a single input into an array
function traverseObject(object){
// iterate through the object
for (var i in object){
// if the next key exists, run again
if(object[i] !== null && typeof(object[i])=="object"){
traverseObject(object[i]);
} else {
var value = [object[i]];
// if the value contains a comma
if(value.toString().indexOf(',') > -1){
// set the *nested* key to the
// value as an array by splitting at the commas
object[i] =value.toString().split(',').filter(function(el){
// remove the extra entry after splitting
return el.length != 0;
});
}
}
}
}
traverseObject(json);
$('#test').on('click', function(){
console.log(json)
});
Update your config.set() as follows:
var json = {};
config = {
set: function(keyValueString) {
var pair = keyValueString.split('=');
// left of the = is the key path
var keyPath = pair[0];
// right of the = is the value to set
var value = pair[1];
// split keyPath into an array of keys
var keys = keyPath.split('.');
var key;
var currentObj = json;
// loop through all keys in the key path, except the last one.
// this creates the object structure implied by the key path.
// we want to do something different on the last iteration.
for (var i=0; i < keys.length-1; i++) {
// Get the current key we are looping
key = keys[i];
// if the requested level on the current object doesn't exist,
// make a blank object.
if (typeof currentObj[key] === 'undefined') {
currentObj[key] = {};
}
currentObj = currentObj[key];
}
// our loop doesn't handle the last key, because that's when we
// want to set the actual value.
var lastKey = keys[keys.length-1]
if (typeof currentObj[lastKey] === 'undefined') {
// set string if nothing exists
currentObj[lastKey] = value;
} else if(!Array.isArray(currentObj[lastKey])) {
// if exists and is not an array,
// create an array with two items
// previously stored value (string) with lastKey key
// current value
var previous = { [lastKey]: currentObj[lastKey] };
var current = { [lastKey]: value };
currentObj[lastKey] = [previous, current];
} else if(Array.isArray(currentObj[key])){
// if exists and is an array
// push the new object to it
var current = { [lastKey]: value }
currentObj[lastKey].push(current);
}
}
};
// iterate through all of our inputs, and nest them based off their data-* attribute
$('input').each(function(){
// set nest = value setup, e.g. parent.child.grandchild = first
// we then break this
var key = $(this).attr('data-nest') + '=' + $(this).val();
config.set(key);
});
// as a bonus - this is how I went about breaking multiple values within a single input into an array
function traverseObject(object){
// iterate through the object
for (var i in object){
var value = [object[i]];
// EDIT: continue only if value is not an array
if(!Array.isArray(object[i])) {
// if the value contains a comma
if(value.toString().indexOf(',') > -1){
// set the *nested* key to the
// value as an array by splitting at the commas
object[i] = value.toString().split(',').filter(function(el){
// remove the extra entry after splitting
return el.length != 0;
});
}
// if the next key exists, run again
if(object[i] !== null && typeof(object[i])=="object"){
traverseObject(object[i]);
}
}
}
}
traverseObject(json);
$('#test').on('click', function(){
console.log(json)
});
#test{
padding: 5px;
border: 1px solid black;
font-size: 15px;
cursor: pointer;
width: 150px;
margin: 5px;
text-align: center;
}
input{
display: block;
margin: 5px;
padding: 5px;
width: 150px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label>Below are unique tags (working fine)</label>
<input type="text" data-nest="parent.child.grandchild1" value="gchild1-first"/>
<input type="text" data-nest="parent.child.grandchild2" value="gchild2-second"/>
<label>Below is multiple occurances of the same tag (find a way to break these into an array of objects)</label>
<input type="text" data-nest="parent.child.grandchild" value="gchild-first"/>
<input type="text" data-nest="parent.child.grandchild" value="gchild-second"/>
<label>Single array example</label>
<input type="text" data-nest="parent.child.array" value="this,is,an,array"/>
<div id="test">
Test
</div>
Try this https://jsfiddle.net/ado7eLL9/19/
by updating the set method of config like this
if (typeof currentObj[lastKey] === 'undefined') {
currentObj[lastKey] = value;
} else if(!Array.isArray(currentObj[lastKey])) {
currentObj[lastKey] = [currentObj[lastKey], value];
} else if(Array.isArray(currentObj[key])){
currentObj[lastKey].push(value);
}
This problem has been solved by attacking with a different approach.
We set the element we want as the array with [] added to the end of its data-nest attribute - we can then use this as the baseline for what we want converted.
If anyone is curious, here's the updated fiddle

Remove duplicates in array separated by double commas in JavaScript

I have an array in JavaScript like this
var data = [,A_1_VII,VII,V2,,A_1_VII,VII,V2,,A_1_VII,VII,V2,,B_1_XIV,XIV,V3,,B_2_XVI,XVI,V3]
when I alert in JavaScript it gives as below
,A_1_VII,VII,V2
,A_1_VII,VII,V2
,A_1_VII,VII,V2
,B_1_XIV,XIV,V3
,B_2_XVI,XVI,V3
But I want like this which is duplicates removed array
var unique_data = [,A_1_VII,VII,V2,,B_1_XIV,XIV,V3,,B_2_XVI,XVI,V3]
On alert it should give like this
,A_1_VII,VII,V2
,B_1_XIV,XIV,V3
,B_2_XVI,XVI,V3
First Thing your array contains string as a constant that's not going to work.
Secondly, if all of you value are strings you can do it as follows:
var data =[,"A_1_VII","VII","V2",,"A_1_VII","VII","V2",,"A_1_VII","VII","V2",,"B_1_XIV","XIV","V3",,"B_2_XVI","XVI","V3"];
var uniqueArray = data.filter(function(item, pos) {
return data.indexOf(item) == pos;
})
alert(uniqueArray);
Assuming the variables in your array are well defined, you can clean it up and remove duplicates with a for loop:
var data [/* ... */];
var unique_data = [];
for(let i = 0; i < data.length; i++) {
if (data[i] && unique_data.indexOf(data[i]) === -1) {
unique_data.push(data[i]);
}
}
Please note that the code above assumes that your array contains non-object types, otherwise the solution would need to use something more sophisticated than indexOf().
You can create your unique function to remove duplicate entry and empty value from array like this.
var data =[,"A_1_VII,VII","V2,,A_1_VII","VII","V2",,"A_1_VII","VII","V2",,"B_1_XIV,XIV","V3",,"B_2_XVI,XVI,V3"]
var unique_data = uniqueList(data);
alert(unique_data);
function uniqueList(list) {
var uniqueResult = [];
$.each(list, function(i, e) {
if ($.inArray(e, uniqueResult) == -1 &&$.inArray(e, uniqueResult)!="")// chech for unique value and empty value
uniqueResult.push(e);
});
return uniqueResult ;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Check json data for value and then get its key

I have some JSON data that I am retrieving from https://status.mojang.com/check and am storing in a variable. I'm still quite new to JSON/JS and I can't seem to find any answers on google.
Code:
function checkMojang() {
var mojangStatus = mojang.status();
mojangStatus.then(function (message) {
var response = JSON.parse(message);
})
}
Data I am using can be seen at the link above. I am trying to check all the data in the json array, see if any of the values contain "yellow" or "red" and get the keys for those values along with their checked value but can't figure out how to do so.
You can loop through the array and then through the object properties and make a new object using the colors as keys
var response = [{"minecraft.net":"green"},{"session.minecraft.net":"red"},{"account.mojang.com":"green"},{"auth.mojang.com":"green"},{"skins.minecraft.net":"green"},{"authserver.mojang.com":"yellow"},{"sessionserver.mojang.com":"green"},{"api.mojang.com":"green"},{"textures.minecraft.net":"green"},{"mojang.com":"red"}];
var new_response = {};
response.forEach(function(obj){
for (var prop in obj) {
if(obj.hasOwnProperty(prop)) {
if(new_response[obj[prop]] == undefined) new_response[obj[prop]] = [];
new_response[obj[prop]].push(prop);
}
}
})
console.log(new_response);
The you can use the object for your needs as
new_response["red"]
giving you the list of all key with red value.
you can use the method array.foreach() to execute a provided function once per array element and the for ... in to itarate over the enumarable properties.
So you can test the value and get keys for the value "yellow" or "red"
response.forEach(function(element) {
for (k in element) {
if (element[k]=="red" or element[k]=="yellow") {
// k is the key
}
}
});
function checkMojang() {
var mojangStatus = mojang.status();
mojangStatus.then(function (message) {
var response = JSON.parse(message);
for (i = 0; i < response.length; i++) { // iterate over response array
var item = response[i]; // get item from array
var key = Object.keys(item)[0]; // get the key of the item
var value = item[key]; // get the value of the item
if (value === 'yellow' || value === 'red') {
// do something, like adding it to a list
}
}
});
}

Add values from one array to object with specified key & index

Im using the following code,
jQuery.each(aDataSel, function(index, oData) {
oPushedObject = {};
aSelectedDataSet.push(fnCreateEnt(aProp, oData, oPushedObject));
});
This is aSelectedDataSet values
and this is the values of OData
What I need is that before I do the push is to fill the listTypeGroup & listTypeGroupDescription (with the red arrow ) with values that Are inside the oData -> ListTypeGroupAssigment -> result (listTypeGroup & listTypeGroupDescription) , The index is relevant since I want to add just the value of the index in each iteration (since this code is called inside outer loop and the index determine the current step of the loop) ,How it can be done nicely?
The result contain 100 entries (always) and the a selected data will have 100 entries at the end...
Update :)
Just to be clear In the pic I show the values which is hardcoded for this run but the values can be any values, we just need to find the match between the both objects values...
I mean to find a match between to_ListTypeGroupAssigment in both object (which in this case exist ) and if in oData there is result bigger then one entry start with the matching ...
UPDATE2 - when I try Dave code the following happen for each entry,
This happen in the Jquery.extend line...any idea how to overcome this?
The following hard-coded of Dave:-) work perfect but I need generic code which doesnt refer to specific field name
jQuery.each(aDataSet, function(index, oData) {
oPushedObject = {};
fnCreatePushedEntry(aProperties, oData, oPushedObject);
var result = oData.to_ListTypeGroupAssignment.results[index];
oPushedObject.to_ListTypeGroupAssignment = {
ListTypeGroup: result.ListTypeGroup,
ListTypeGroupDescription: result.ListTypeGroupDescription
};
aSelectedDataSet.push(oPushedObject);
});
Im stuck :(any idea how to proceed here ?what can be wrong with the extend ?
should I use something else ? Im new to jQuery...:)
I think that this happen(in Dave answer) because the oData[key] is contain the results and not the specified key (the keyValue = to_ListTypeGroupAssignment ) which is correct but we need the value inside the object result per index...
var needValuesForMatch = {
ListTypeGroup: 'undefined',
ListTypeGroupDescription: 'undefined',
}
//Just to show that oPushedObject can contain additional values just for simulation
var temp = {
test: 1
};
//------------------This object to_ListTypeGroupAssigment should be filled (in generic way :) ------
var oPushedObject = {
temp: temp,
to_ListTypeGroupAssignment: needValuesForMatch
};
oPushedObject is one instance in aSelectedDataSet
and after the matching I need to do the follwing:
aSelectedDataSet.push(oPushedObject);
Is this what you're after:
OPTION ONE - DEEP CLONE FROM oData TO aSelectedDataSet
aSelectedDataSet.forEach(function(currentObject,index){
for (var childObject in currentObject) {
if (! currentObject.hasOwnProperty(childObject))
continue;
var objectToClone = oData[childObject]['results'][index];
if(objectToClone)
$.extend(true,currentObject[childObject],objectToClone);
}
});
Here is your data in a fiddle with the function applied: https://jsfiddle.net/hyz0s5fe/
OPTION TWO - DEEP CLONE FROM oData ONLY WHERE PROPERTY EXISTS IN aSelectedDataSet
aSelectedDataSet.forEach(function(currentObject,index){
for (var childObject in currentObject) {
if (! currentObject.hasOwnProperty(childObject))
continue;
if(typeof currentObject[childObject] !== 'object')
continue;
for(var grandChildObject in currentObject[childObject]) {
var objectToClone = oData[childObject]['results'][index][grandChildObject];
if(typeof objectToClone === 'object') {
$.extend(true,currentObject[childObject][grandChildObject],objectToClone);
} else {
currentObject[childObject][grandChildObject] = objectToClone;
}
}
}
Fiddle for option 2: https://jsfiddle.net/4rh6tt25/
If I am understanding you correctly this should just be a small change:
jQuery.each(aDataSel, function(index, oData) {
oPushedObject = {};
fnCreateEnt(aProp, oData, oPushObj);
//get all the properties of oData and clone into matching properties of oPushObj
Object.getOwnPropertyNames(oData).forEach(function(key) {
if (oPushObj.hasOwnProperty(key)) {
//oPushObj has a matching property, start creating destination object
oPushObj[key] = {};
var source = oData[key];
var destination = oPushObj[key];
//can safely assume we are copying an object. iterate through source properties
Object.getOwnPropertyNames(source).forEach(function(sourceKey) {
var sourceItem = source[sourceKey];
//handle property differently for arrays
if (Array.isArray(sourceItem)) {
//just copy the array item from the appropriate index
destination[sourceKey] = sourceItem.slice(index, index + 1);
} else {
//use jQuery to make a full clone of sourceItem
destination[sourceKey] = $.extend(true, {}, sourceItem);
}
});
}
});
aSelectedDataSet.push(oPushedObject);
});
It is unclear what exactly your fnCreateEnt() function returns though. I am assuming it is the populated oPushObj but it's not entirely clear from your question.

javascript dynamically add values to array

I'm trying to loop over the checkboxes in a form and add their values to a multidimensional javascript object. The 'attrib' data attribute will be the key. Possible key values are 'category', 'product_group' and 'language' but I'd rather add them dynamically in case any more get added in the future.
I want to end up with an object like this, which I can easily send as a json_encode 'd single value to the server.
values = {
'category' : {1,2,3},
'product_group' : {4,5,6},
'language': {'en','fr','de'}
};
Code below. Here obviously each iteration overwrites existing values instead of adding to it. I'm unsure where I can create values[key] as an object ... ?
$('.filter input, .multiselect-container input').change(function() {
var values = {}
$('.filter input:checked').each(function() {
if($(this).is(':checked')) {
var key = $(this).data('attrib')
var value = $(this).val()
values[key] = value
// values[key].push(value) = calling method push of undefined ...
}
else {
// Remove value
}
})
console.log(values)
})
Your error is due to the fact that values[key] is undefined, therefore does not have a push method.
Try this code:
if($(this).is(':checked')) {
var key = $(this).data('attrib')
var value = $(this).val()
values[key] = values[key] || [] // initialize with empty array
values[key].push(value)
}
Not sure that's what you are looking for:
if(!values[key])
values[key]=new Array();
values[key].push(value);
But this way you can add an array of value to every key.
Try this:
if($(this).is(':checked')) {
var key = $(this).data('attrib')
var value = $(this).val()
if(typeof values[key] == "undefined")
values[key] = [];
values[key].push(value);
}
else {
// Remove value
}
First, your data representation is not correct. The object attributes should be arrays like this:
values = {
'category' : [1,2,3],
'product_group' : [4,5,6],
'language': ['en','fr','de']
};
With that data representation, this piece of code will do what you want:
$('.filter input, .multiselect-container input').change(function() {
var values = {}
$('.filter input:checked').each(function() {
if($(this).is(':checked')) {
var key = $(this).data('attrib')
var value = $(this).val()
values[key] = value
if (values.key == undefined){
//Check if key exists. If not, create it as an array
values[key] = Array()
values[key].push(value)
}
else{
values[key].push(value)
}
}
else {
// Remove value
}
})
console.log(values)
})

Categories