JavaScript - Maintain Object key value order - javascript

My required object key-value(property-value) Order : {three:3,two:2,one:1}
I want last added key at top,When i add key-value dynamically the order i got is given below,
var numObj={};
numObj["one"]=1;
numObj["two"]=2;
numObj["three"]=3;
console.log(numObj) // result i get is { one:1, three:3,two:2 }
Please any one help me to get this key-value order {three:3,two:2,one:1}

As the commenters point out, JavaScript objects have no defined order for iteration. However, JavaScript maps do: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map.
let aMap = new Map();
myMap.set('AKey1', 'AValue1');
myMap.set('AKey2', 'AValue2');
myMap.set('AKey3', 'AValue3');
for (let x of aMap) {
console.log(x[1]);
}
Will provide
AValue1
AValue2
AValue3

Related

Map.delete() not working on key in parent Map

What I'm doing right now, is deleting any diff that doesn't contain the string, and if the diff's dictionary is empty, then i try to delete the map.
the issue here is that, i can't delete a map with data.delete(map) for some reasons (no errors in console) and any piece of code located after that deletion in the if statement won't run.
here is the code in question:
var data = new Map({"593620 Linked Horizon - Shinzou o Sasageyo! [TV Size]": {"difficulties": {"Titan": 86813}}, "859608 LiSA - ADAMAS (TV Size)": {"difficulties": {"Kibbleru's Blue Rose": 899}},"940746 CHiCO with HoneyWorks - Kimi ga Sora Koso Kanashikere": {"difficulties": {"Taeyang's Extra": 72321}}});
var string = "titan";
Array.from(data.keys()).forEach(function(map) {
if (!(map.toLowerCase().indexOf(string.toLowerCase()) >=0)) {
if (document.getElementById("diff_search_box").checked) {
Array.from(data.get(map).get("difficulties").keys()).forEach(function(diff) {
if (!(diff.toLowerCase().indexOf(string) >= 0)) {
data.get(map).get("difficulties").delete(diff)
}
})
if (Array.from(data.get(map).get("difficulties").keys()).length = 0) {
data.delete(map)
}
}
}
})
in this situation, I'm supposed to get a dictionary such as:
{
"593620 Linked Horizon - Shinzou o Sasageyo! [TV Size]": {
"difficulties": {"Titan": 86813}
}
}
Huge number of problems with this code. My recommendation is don't write so much code without running it to make sure it works first. Write small pieces at a time and run it as you go making sure everything works along the way.
Issue number one is you cannot initialize a map with an object like that. The Map must be initialized with an array of arrays that are each two elements long, each containing the key value pairs for the map. You can fix this by wrapping the object in Object.entries() as that will return the key vale pairs for the object.
Second problem is titan is a string so it should be "titan".
Number three, you're calling .get on an object in the line data.get(map).get("difficulties"). Objects do not have .get, you have to use brackets or dot syntax: data.get(map).difficulties or data.get(map).difficulties.
Fourth, I think you don't actually want to delete the data from the map. If you did, when the user changes the search text the old data would still be gone.
Why are you using map anyways? you can simply use a normal object.
Just do this if you must use maps:
var data = new Map(Object.entries({
"593620 Linked Horizon - Shinzou o Sasageyo! [TV Size]": {
"difficulties": {"Titan": 86813}
},
"859608 LiSA - ADAMAS (TV Size)": {
"difficulties": {"Kibbleru's Blue Rose": 899}
},
"940746 CHiCO with HoneyWorks - Kimi ga Sora Koso Kanashikere": {
"difficulties": {"Taeyang's Extra": 72321}
}
}));
var string = 'titan';
function search(s) {
var r = {};
for( const [key, value] of data ) {
for( const diffKey in value.difficulties ) {
if(diffKey.toLowerCase().indexOf(string) != -1)
r[key] = value;
}
}
return new Map(Object.entries(r));
}
With this function, you can do search(string) and it will return you the map that you were wanting originally.
Mainly you should writing a bunch of code without running anything.
Map needs an iterable like an array passed to it such as:
new Map([['Key 1', 'Value 1'], ['Key 1', 'Value 1']])
You can't pass an object literal to it but you can easily use Object.entries() to extract the needed array from your object.
Then you can use Map.prototype.forEach() to loop over all the Map entries
var data = {"593620 Linked Horizon - Shinzou o Sasageyo! [TV Size]": {"difficulties": {"Titan": 86813}}, "859608 LiSA - ADAMAS (TV Size)": {"difficulties": {"Kibbleru's Blue Rose": 899}},"940746 CHiCO with HoneyWorks - Kimi ga Sora Koso Kanashikere": {"difficulties": {"Taeyang's Extra": 72321}}};
const map = new Map(Object.entries(data));
map.forEach((value, key) =>{
const {difficulties} = value;
console.log('Map key:', key.toLowerCase());
// if(someCondition){
// map.delete(key)
// }
Object.entries(difficulties).forEach(([k,v])=>{
console.log('Diff key:', k, ' Diff value:', v)
// if(k.toLowerCase().includes('titan')){
// delete difficulties[key];
// }
})
console.log('*****************************')
})
surprising to see none of the previous answer saw that, another person on a discord server i do support for software stuff on pointed out the last if condition and the fact it's missing a = so it appear as
if (Array.from(data.get(map).get("difficulties").keys()).length == 0) {
// was = before, == now
data.delete(map)
}
so now i indeed obtain a data dictionary with only 1 element containing the map which also have the difficulty that's contained in the specified string.

Check if an object contains a property called format in Javascript

I have an array of movie objects in a web application, and each object has properties for title(string),release year(int),rating(int) and genre(an array of string e.g ['Action','Sci-Fi],now some of the movie objects got a property for format(string) while others don't.All I need is help iterating through these objects and checking which objects don't have a format property and add the property to these objects and set the values with Film for those that do not...
Here is the js code i tried so far
var fractured={
title:"Fractured",
release:2019,
rating:8,
format:"digital",
genre:[
"Mystery","Sci-Fi","Western"]
};
var countdown={
title:"Countdown",
release:2018,
rating:5,
genre:["Sci-Fi","Mystery","Western"]
}
var bloodshot={
title:"Bloodshot",
release:2020,
rating:6,
format:"digital",
genre:["Sci-Fi","Action"]
}
var revenant={
title:"Revenant",
release:2015,
rating:3,
genre:["History","Western","Action"]
}
var crisis={
title:"Crisis",
release:2016,
rating:10,
genre:["Action","Drama","Reality"]
}
var life={
title:"Life",
release:2017,
rating:9,
format:"digital",
genre:["Sci-Fi","Action","Mystery"]
}
var nmovies=new Array(fractured,life,crisis,revenant,bloodshot,countdown);
//This line outputs the title property of the first object in nmovies;
console.log(nmovies[0].title);
//this is the iteration that needs to check if an object has a format property and add it with the value 'Film'
nmovies.forEach(myfunction());
function myfunction(item, index){
//Code to check please
}
Thank you for your input.
I am new to JavaScript but hopefully that works.
function myfunction(item, index) {
if (!item.hasOwnProperty("format")) {
item.format = "Film";
}
}

Why is my code behaving like I have duplicate keys in a dictionary despite using unique strings? Javascript / Appscript

I am trying to loop through a dictionary of customers and save energy usage data, but for some customers when I try to change the values in their usage dictionary it will also change a completely different customer's value. I have a nested dictionary with customer utility information, the top-level key being a unique internal ID.
I stripped my code down to a single loop, looping through the top-level keys and setting the same month's usage for all customers in the dictionary to be the value of the iterator. After that, as shown in the code sample below, I log the values for three customers. After that, I increment only one of those customer's usage, and log the values again. The console shows that two over the customer's have dictionaries that are tied together somehow, but I can't figure out why or how to solve this. I can't discern any pattern in the keys of the linked customers, either.
Structure of the nested dictionary:
CustDict =
{"N0100000XXXXXX" =
{"name" = "XXXX"},
{"address" = "XXXX"},
{"meter_read_dates" =
{"2021-05-13" =
{"usage" = "XXXX"}
}
}
}
Stripped down code I used to demonstrate what is happening as simply as possible (real ID values):
Logger.log(custDict["N01000009700816"]["meter_read_dates"]["2021-05-13"]["usage"])
Logger.log(custDict["N01000000419887"]["meter_read_dates"]["2021-05-13"]["usage"])
Logger.log(custDict["N01000012580668"]["meter_read_dates"]["2021-05-13"]["usage"])
custDict["N01000009700816"]["meter_read_dates"]["2021-05-13"]["usage"] =
custDict["N01000009700816"]["meter_read_dates"]["2021-05-13"]["usage"] + 1
Logger.log(custDict["N01000009700816"]["meter_read_dates"]["2021-05-13"]["usage"])
Logger.log(custDict["N01000000419887"]["meter_read_dates"]["2021-05-13"]["usage"])
Logger.log(custDict["N01000012580668"]["meter_read_dates"]["2021-05-13"]["usage"])
Console Output:
11:54:56 AM Info 346.0
11:54:56 AM Info 346.0
11:54:56 AM Info 322.0
11:54:56 AM Info 347.0
11:54:56 AM Info 347.0
11:54:56 AM Info 322.0
Code used to create the CustDict dictionary:
stmtCR = conn.prepareStatement('SELECT cust_id, utility_account, cycle_id, read_cycle FROM customers')
results = stmtCR.executeQuery()
resultsMetaData = results.getMetaData()
numCols = resultsMetaData.getColumnCount();
results.last();
numRows = results.getRow();
i = 0
results.first()
var custDict = {}
while (i < numRows)
{
custDict[results.getString(1)] = {}
custDict[results.getString(1)]["id"] = results.getString(1)
custDict[results.getString(1)]["utility_account"] = results.getString(2)
custDict[results.getString(1)]["cycle_id"] = results.getString(3)
custDict[results.getString(1)]["read_cycle"] = results.getString(4)
results.next()
i++;
}
for (i = 0; i < Object.keys(custDict).length; i++)
{
tempCust = custDict[Object.keys(custDict)[i]]
tempCycleId = tempCust["cycle_id"]
tempReadCycle = tempCust["read_cycle"]
tempCust["meter_read_dates"] = cycleIdShdDict[tempCycleId][tempReadCycle]
custDict[Object.keys(custDict)[i]] = tempCust
}
cycleIdShdDict is a seperate dictionary that contains a set of dates associated with each cycle_id and read_cycle
I suspect the problem is that Object.keys(custDict) is returning the keys in a different order at different places in the for loop. So you're getting the object from one key, and then assigning it to a different key.
There's no need to assign back to custDict[Object.keys(custDict)[i]] since you're modifying the object in place, not a copy.
But instead of looping through the keys, loop through the values and modify them.
Object.values(custDict).forEach(tempCust => {
let tempCycleId = tempCust["cycle_id"];
let tempReadCycle = tempCust["read_cycle"];
tempCust["meter_read_dates"] = cycleIdShdDict[tempCycleId][tempReadCycle];
});

How to compare a 2-D array and 1-D Array and to Store common Data in Another Array in Java Script

I have 2 Arrays and one is 2 dimensional and another is 1 dimensional. I need to compare both and need to store there common data in another array. I tried the below approach:-
tw.local.listtodisplayNW = new tw.object.listOf.listtodisplayNWBO();
//if(tw.local.SQLResults[0].rows.listLength >
// tw.local.virtualServers.listLength)
var k=0;
for (var i=0;i<tw.local.SQLResults[0].rows.listLength;i++)
{
log.info("Inside SQLResults loop - For RuntimeID: "
+tw.local.SQLResults[0].rows[i].data[3]);
for(var j=0;j<tw.local.virtualServers.listLength;j++)
{
log.info("Inside API loop - For RuntimeID: "
+tw.local.virtualServers[j].runtimeid);
if(tw.local.SQLResults[0].rows[i].data[3] ==
tw.local.virtualServers[j].runtimeid)
{
tw.local.listtodisplayNW[k] = new tw.object.listtodisplayNWBO();
tw.local.listtodisplayNW[k].vsysName =
tw.local.virtualServers[j].virtualSystemName;
tw.local.listtodisplayNW[k].vsysID =
tw.local.virtualServers[j].virtualSystemId;
tw.local.listtodisplayNW[k].serverName =
tw.local.virtualServers[j].serverName;
tw.local.listtodisplayNW[k].serverID =
tw.local.virtualServers[j].serverId;
tw.local.listtodisplayNW[k].runtimeID =
tw.local.virtualServers[j].runtimeid;
//tw.local.listtodisplayNW[k].IPAddress =
tw.local.virtualServers[j].nics[j].ipAddress;
log.info("VsysName:
"+tw.local.listtodisplayNW[k].vsysName+"RuntimeID:
"+tw.local.listtodisplayNW[k].runtimeID);
//tw.local.listtodisplayNW[k] = new
tw.object.listtodisplayNWBO();
tw.local.listtodisplayNW[k].currentSpeed =
tw.local.SQLResults[0].rows[i].data[5];
log.info("VsysName:
"+tw.local.listtodisplayNW[k].vsysName+"RuntimeID:
"+tw.local.listtodisplayNW[k].runtimeID+"CurrentSpeed:
"+tw.local.listtodisplayNW[k].currentSpeed);
if(tw.local.listtodisplayNW[k].currentSpeed != "100 Mbps")
{
tw.local.listtodisplayNW[k].desiredSpeed = "100 Mbps";
}
else
{
tw.local.listtodisplayNW[k].desiredSpeed = "1 Gbps";
}
log.info("DesiredSpeed:
"+tw.local.listtodisplayNW[k].desiredSpeed);
k++;
}
}
log.info("Length of
listtodisplayNW"+tw.local.listtodisplayNW.listLength);
}
In above code SQLResults is a 2-d array and virtualServers is a 1-D array.
I need to compare both these array and common data need to be store in another array. Here performance is not good. Is there any other way to do this efficiently. Please make a needful favour and Thanks in advance.
Assuming integer data, the following example works on the theme of array implementation of set intersection, which will take care of performance.
Convert 2D array to 1D.
var 2DtoIDArray = 2DArray.join().split(",");
Create an array named marker whose purpose is to serve as a lookup that element.
This needs to be done as follows.
Iterate through the smaller array, say 1DArray and keep setting marker as follows throughout iteration.
marker[1DArray[counter]]='S1';
Now iterate through 2Dto1DArray array(you may use nested loop iteration if you dont want to convert it to 1 dimesnional) and for each element
of this array check if its marked as 'S1' in the marker lookup array.
If yes, keep adding the elements in the commonElementsArray.
Follow this simple approach
Since the matching condition is only one between the two large arrays, create two maps (one for each array) to map each record against that attribute which is to be matched
For SQLResults
var map1 = {};
tw.local.SQLResults[0].rows.each( function(row){
map1[ row.data[3] ] = row;
});
and similarly for virtual servers
var map2 = {};
tw.local.virtualServers.each( function(vs){
map2[ vs.runtimeid ] = vs;
});
Now iterate these two maps wrt to their keys and set the values in new array
new array being tw.local.listtodisplayNW
tw.local.listtodisplayNW = [];
Object.keys( map1 ).forEach( function( key ){
if( map2[ key ] )
{
//set the values in tw.local.listtodisplayNW
}
})
Complexity of the approach is simply O(n) since there is no nested loops.

How can I retrive a value from this json object?

<script>
var output = {"regions":{"4441":"Avtonomna Respublika Krym","4431":"Cherkas'ka Oblast'","4432":"Chernihivs'ka Oblast'","4433":"Chernivets'ka Oblast'","4434":"Dnipropetrovs'ka Oblast'","4435":"Donets'ka Oblast'","4436":"Ivano-Frankivs'ka Oblast'","4437":"Kharkivs'ka Oblast'","4438":"Khersons'ka Oblast'","4439":"Khmel'nyts'ka Oblast'","4440":"Kirovohrads'ka Oblast'","4443":"Kyyivs'ka Oblast'","4445":"L'vivs'ka Oblast'","4444":"Luhans'ka Oblast'","4442":"Misto Kyyiv","4450":"Misto Sevastopol","4446":"Mykolayivs'ka Oblast'","4447":"Odes'ka Oblast","4448":"Poltavs'ka Oblast'","4449":"Rivnens'ka Oblast'","4451":"Sums'ka Oblast'","4452":"Ternopil's'ka Oblast'","788":"Ukraine","4453":"Vinnyts'ka Oblast'","4454":"Volyns'ka Oblast'","4455":"Zakarpats'ka Oblast'","4456":"Zaporiz'ka Oblast'","4457":"Zhytomyrs'ka Oblast'"}}
alert(output.regions[1]);
</script>
This part gives me undefined:
alert(output.regions[1]);
How can I grab the first key/value pair for example. Basically I need to turn this into a select dropdown, the numeric keys would be the values and the names of the cities would be the option text.
Can iterate over it like:
for(key in output.regions) {
alert(key +' => '+output.regions[key]); // 4441 => Avtonomna Respublika Krym ...etc
}
Rather than a numeric index, you'll want to key into regions with the keys you've specified, like 4441, 4431, etc:
var output = {"regions":{"4441":"Avtonomna Respublika Krym","4431":"Cherkas'ka Oblast'","4432":"Chernihivs'ka Oblast'","4433":"Chernivets'ka Oblast'","4434":"Dnipropetrovs'ka Oblast'","4435":"Donets'ka Oblast'","4436":"Ivano-Frankivs'ka Oblast'","4437":"Kharkivs'ka Oblast'","4438":"Khersons'ka Oblast'","4439":"Khmel'nyts'ka Oblast'","4440":"Kirovohrads'ka Oblast'","4443":"Kyyivs'ka Oblast'","4445":"L'vivs'ka Oblast'","4444":"Luhans'ka Oblast'","4442":"Misto Kyyiv","4450":"Misto Sevastopol","4446":"Mykolayivs'ka Oblast'","4447":"Odes'ka Oblast","4448":"Poltavs'ka Oblast'","4449":"Rivnens'ka Oblast'","4451":"Sums'ka Oblast'","4452":"Ternopil's'ka Oblast'","788":"Ukraine","4453":"Vinnyts'ka Oblast'","4454":"Volyns'ka Oblast'","4455":"Zakarpats'ka Oblast'","4456":"Zaporiz'ka Oblast'","4457":"Zhytomyrs'ka Oblast'"}}
alert(output.regions[4441]); // alerts "Avtonomna Respublika Krym"
The regions entity is an object and not an array so you have to select its attribute by its associated key.
output.regions.4441
or
output.regions['4441']
The value with the key "regions" is a map, not an array - it has no ordering, therefore there is no concept of "first key/value pair" - you'll have to impose your own ordering if you want one.
This is because output.regions is an object, not an array. You would either need to access by the ID (778) or if you don't know it, than you can iterate to find it.
for (k in output.regions) { var key = k; break; }
alert(output.regions[key]);
There is no "first" value. Properties of javascript objects are not ordered. You can iterate over a javascript object like this:
for(key in output.regions){
alert(output.regions[key])
}
and check for the cycle of iteration, but there's no guarantee that the order won't change unexpectedly. To have a guaranteed order, you need to use an array.

Categories

Resources