Loop over an object in JavaScript - javascript

I must do this: to work over string that i will ask to some user:
text = "";
arr = ["*****"];
arr2 = [];
text = arr.toString();
for(i=0; i<text.length; i++) {
arr2.push(text[i]);
}
---> arr2 = [*,*,*,*,*] <--- thats what i want!.
But i must work with a lot of data like this, so i created and array to content that structured data:
var gems = [
{
name: 'Level-1',
row: {
r1: '*****',
r2: '-***-',
r3: '--*--'
},
canPushtoDb: true,
hideLevel: false,
status: 1
//canvas
},
{
name: 'Level-2',
row: {
r1: '**-**',
r2: '-*-*-',
r3: '-***-',
},
canPushtoDb: true,
hideLevel: false,
status: 1
//canvas
},
{
name: 'Level-3',
row: {
r1: '*-*-*',
r2: '**-**',
r3: '*-*-*'
},
canPushtoDb: true,
hideLevel: true,
status: 1
//canvas
}
];
I want to loop within gems to convert that string on some kind of array, just like I wrote on the beginning of this question.
I was looking on an Angular example, which wrap those objects with a controller.
But for now I'm far to get my code on some refactored version of his own. I just need some hard-coded function or method likegems.name[0].row.r1(this is not working to me!) to get out the object all that I'm working on.

You can iterator over gems as such:
for(var i = 0; i < gems.length; i++) {
...
}
You can then loop through the object as such (within your for loop above)
$.each(var obj in row) {
...Do something with each object found in row
}
To access hardcoded object, your issue was gems.name[0].row.r1
When it should just be gems[0].row.r1

As pointed out by #Patrick Evans, your code is correct except for the fact that arr2 should be arr2 = gems[0].row.r1. Have a look at this JSFiddle.

Related

How to get max and min value from Array in Javascript?

i had seen lots of another examples like
Math.max(...Array1) or Math.max(null,num) or Math.max.apply(null,num)
but it's not working by my code
my data size is 255 and This is what the data looks like when i print it by console.log
0: 55.47999954223633
1: 56.040000915527344
2: 57.52000045776367
3: 57.119998931884766
...
Data was extracted from the json file and then put into the array through push.
code is look like this
let Array =[]
jQuery.getJSON( "price.json",function(data){
for(let i=0;i<data.length;i++){
Array.push(data[i].price)
}
let maximum = Math.max(...Array) // not working
Thank you for reading this.
Math.max(...[]) is ES6 syntax. Maybe you are using an older JavaScript engine? Here are two versions using your data as input, one for newer ES6, one for older ES5:
const dataFromJson = [
{ name: "A", price: 55.47999954223633 },
{ name: "A", price: 56.040000915527344 },
{ name: "A", price: 57.52000045776367 },
{ name: "A", price: 57.119998931884766 }
];
// ES6:
let arr1 = dataFromJson.map(obj => obj.price);
let max1 = Math.max(...arr1);
console.log('ES6 max: ' + max1);
// ES5:
let arr2 = dataFromJson.map(function(obj) {
return obj.price;
});
let max2 = Math.max.apply(null, arr2);
console.log('ES5 max: ' + max2);
Output:
ES6 max: 57.52000045776367
ES5 max: 57.52000045776367

Values from last FOR loop over all, after FOR is done

I have a function which get a json as parameter, build another json with some values from given json and return builded json.
function getMyJSON(json) {
var result = {
lastUpdate: "",
legends: null
};
result.legends = (new Array(json.legends.length)).fill({
name: null,
rgb: null,
values: null
});
for (let j = 0; j < json.legends.length; j++) {
result.legends[j].name = json.legends[j].name;
result.legends[j].rgb = json.legends[j].rgb;
result.legends[j].values = (new Array(10)).fill(0);
console.log(result.legends[0].name); //PRINT ONLY FIRST ELEMENT
}
console.log(result.legends);
return result;
}
The problem appear after for loop is done. All result.legends have the same value from the last json.legends
Here is how output look:
The legends.name of first element(result.legends[0].name) is changed after every loop.
At the end, all legends.name from result are equal with the last legends.name from json. Why?
I found on google that it is something about variable scope, but I can't figure it out how to do this.
You need independent objects inside of the array. Array#fill takes the same object reference and this leads to the same result in each object.
Instead of this, you could create a new array with Array.from and map new objects with the second parameter for a callback.
result.legends = Array.from(
{ length: json.legends.length },
_ => ({ name: null, rgb: null, values: null })
);
#NinaScholz has described the problem and solved it, however as I mentioned in the comments on the question you can improve and simplify the logic by using map():
var obj = {
legends: [{
name: 'foo',
rgb: 'C00'
},{
name: 'bar',
rgb: 'FFF'
},{
name: 'fizz',
rgb: 'CCFFCC'
},{
name: 'buzz',
rgb: '000000'
}]
}
console.log(getMyJSON(obj));
function getMyJSON(o) {
return {
lastUpdate: "",
legends: o.legends.map(function(item) {
return {
name: item.name,
rgb: item.rgb,
values: (new Array(10)).fill(0)
}
})
};
}

Can someone explain me how to use paraments correctly in this example?

I'm trying JS. I have used only Python recently.
And there is a problem, look at this example:
var myCharacter = {
name: "character",
avatarImage: "avatar.png",
experience: 1,
level: 1,
items: {helmetSlot: blank, armorSlot: blank}, //'items' will be changed into 'inventory'
backpack: [],
strength: 0,
//It is corrent 'method'?
takeOff: function(slot) {
if (this.backpack.length < 10) { //setting backpack length
this.backpack.push(this.items.slot)
this.items.slot = blank
}
else {}
}
}
myCharacter.takeOff(helmetSlot) //why it doesn't work? I know it did't declared but ... You know I want to use 'word' helmetSlot to make block 'takeOff' way I want, I have used to do things like this in python
Problem is in method takeOff. Can you explain me how to use it like I can do it in Python?
Here is full code: https://pastebin.com/NP1KLPie
I know I have done it wrong, but how to use it the way I want?
this.items.slot is looking for a property literally named "slot". Instead you can use square brackets to use a variable property name: this.items[slot] (passing a string value into slot.)
var myCharacter = {
name: "character",
avatarImage: "avatar.png",
experience: 1,
level: 1,
items: { helmetSlot: "helmet", armorSlot: "armor" }, // using strings instead of the `blank` variable, just so the results will be visible
backpack: [],
strength: 0,
takeOff: function(slot) {
if (this.backpack.length < 10) {
this.backpack.push(this.items[slot]) // not this.items.slot
this.items[slot] = "empty" // string instead of `blank` again
} else {}
}
}
myCharacter.takeOff("helmetSlot") // pass a string, not a bare variable name
console.log(myCharacter) // check the results
in your code values you are using for helmetSlot and armorSlot is not valid .Because in javascript you can can assign one of the below values to variablesor properties of objects
a) String ('' or 'somevalue')
b Number
c) undefined
d) null
e) {}
f) function (){
....
}
var myCharacter = {
name: "character",
avatarImage: "avatar.png",
experience: 1,
level: 1,
items: {helmetSlot:'', armorSlot: ''}, //'items' will be changed into 'inventory'
backpack: [],
strength: 0,
//It is corrent 'method'?
takeOff: function(slot) {
if (this.backpack.length < 10) { //setting backpack length
this.backpack.push(this.items.slot)
this.items.slot = undefined;
}
else {}
}
};
console.log(myCharacter);
myCharacter.takeOff(10);

Extracting data from a complex array without lots of FOR loops

I have a fairly complex array generated from Google's natural language API. I feed it a paragraph of text and out comes lots of language information regarding such paragraph.
My end goal is to find "key words" from this paragraph, so, to achieve this I want to put all the "entities" into a flat array, count the duplicates, and then consider words with the highest amount of duplicates to be "key words". If it doesn't find any then I'll cherry pick words from entities I consider most significant.
I already know the entities that could exist:
var entities = [
'art',
'events',
'goods',
'organizations',
'other',
'people',
'places',
'unknown'
];
Here is an example structure of the array I'm working with.
input = [
{
language: {
entities: {
people: [
{
name: "Paul",
type: "Person",
},
{
name: "Paul",
type: "Person",
},
],
goods: [
{
name: "car",
type: "Consumer_good",
}
], //etc
}
}
}
];
output = ["Paul", "Paul", "car"...];
My question is - what is the best way to convert my initial array into a flat array to then find the duplicates without using a whole bunch of FOR loops?
There is no way around loops or array functions if you work with dynamic input data.
You can access all the values using this format:
input[0]["language"]["entities"]["people"][0].name
input = [
{
language: {
entities: {
people: [
{
name: "Paul",
type: "Person",
},
{
name: "Paul",
type: "Person",
},
],
goods: [
{
name: "car",
type: "Consumer_good",
}
], //etc
}
}
}
];
console.log(input[0]["language"]["entities"]["people"][0].name);
Then you could do something like this:
for (var entry in input[0]["language"]["entities"]) {
console.log(entry);
}
OR, if I understood you wrong,
You can use this to turn the javascript Object into an array using this (requires jquery):
var myObj = {
1: [1, 2, 3],
2: [4, 5, 6]
};
var array = $.map(myObj, function(value, index) {
return [value];
});
console.log(array[0][0]);
console.log(array[0]);
console.log(array);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
This will output
1
[1, 2, 3]
[[1,2,3],[4,5,6]]
You could iterate through input.language.entities in a recursive way and collect all the .name properties into an array. Then you have only one for loop :-).
After doing that, you can iterate through it to find the duplicates. If you sort it alphabetical before it is easier (if two or more consecutive entries are equal, there are duplicates).
But it could be a bit dangerous if google changes the api or if it delivers crap data because of a malfunction.
Isn't input.language.entities already flat enough to work with it?
I ended up doing something like this. It's not pretty but it gets the job done.
var result = [];
var known_entities = ['art','events','goods','organizations','other','people','places','unknown'];
for(i=0; i < known_entities.length; i++){
var entity = known_entities[i];
if(language.entities[entity]){
for(var j in language.entities[entity]){
var word = language.entities[entity][j].name
result.key_words.push(word);
}
}
}

How to Optimize Merge of Two Objects That Include Arrays of Objects

I need to merge two objects in a code path that is going to be heavily used. The code works, but I am concerned it is not optimized enough for speed and I am looking for any suggestions to improve/replace what I have come up with. I originally started working off an example at the end of this issue: How can I merge properties of two JavaScript objects dynamically?. That solution works well for simple objects. However, my needs have a twist to it which is where the performance concerns come in. I need to be able to support arrays such that
an array of simple values will look for values in the new object and add those to the end of the existing object and
an array of objects will either merge objects (based off existence of an id property) or push new objects (objects whose id property does not exist) to the end of the existing array.
I do not need functions/method cloning and I don't care about hasOwnProperty since the objects go back to JSON strings after merging.
Any suggestions to help me pull every last once of performance from this would be greatly appreciated.
var utils = require("util");
function mergeObjs(def, obj) {
if (typeof obj == 'undefined') {
return def;
} else if (typeof def == 'undefined') {
return obj;
}
for (var i in obj) {
// if its an object
if (obj[i] != null && obj[i].constructor == Object)
{
def[i] = mergeObjs(def[i], obj[i]);
}
// if its an array, simple values need to be joined. Object values need to be remerged.
else if(obj[i] != null && utils.isArray(obj[i]) && obj[i].length > 0)
{
// test to see if the first element is an object or not so we know the type of array we're dealing with.
if(obj[i][0].constructor == Object)
{
var newobjs = [];
// create an index of all the existing object IDs for quick access. There is no way to know how many items will be in the arrays.
var objids = {}
for(var x= 0, l= def[i].length ; x < l; x++ )
{
objids[def[i][x].id] = x;
}
// now walk through the objects in the new array
// if the ID exists, then merge the objects.
// if the ID does not exist, push to the end of the def array
for(var x= 0, l= obj[i].length; x < l; x++)
{
var newobj = obj[i][x];
if(objids[newobj.id] !== undefined)
{
def[i][x] = mergeObjs(def[i][x],newobj);
}
else {
newobjs.push(newobj);
}
}
for(var x= 0, l = newobjs.length; x<l; x++) {
def[i].push(newobjs[x]);
}
}
else {
for(var x=0; x < obj[i].length; x++)
{
var idxObj = obj[i][x];
if(def[i].indexOf(idxObj) === -1) {
def[i].push(idxObj);
}
}
}
}
else
{
def[i] = obj[i];
}
}
return def;}
The object samples to merge:
var obj1 = {
"name" : "myname",
"status" : 0,
"profile": { "sex":"m", "isactive" : true},
"strarr":["one", "three"],
"objarray": [
{
"id": 1,
"email": "a1#me.com",
"isactive":true
},
{
"id": 2,
"email": "a2#me.com",
"isactive":false
}
]
};
var obj2 = {
"name" : "myname",
"status" : 1,
"newfield": 1,
"profile": { "isactive" : false, "city": "new York"},
"strarr":["two"],
"objarray": [
{
"id": 1,
"isactive":false
},
{
"id": 2,
"email": "a2modified#me.com"
},
{
"id": 3,
"email": "a3new#me.com",
"isactive" : true
}
]
};
Once merged, this console.log(mergeObjs(obj1, obj2)) should produce this:
{ name: 'myname',
status: 1,
profile: { sex: 'm', isactive: false, city: 'new York' },
strarr: [ 'one', 'three', 'two' ],
objarray:
[ { id: 1, email: 'a1#me.com', isactive: false },
{ id: 2, email: 'a2modified#me.com', isactive: false },
{ id: 3, email: 'a3new#me.com', isactive: true } ],
newfield: 1 }
I'd check out: https://github.com/bestiejs/lodash
_.merge is not on the list of 'optimized' functions, but this is a battle tested, battle hardened. He also has a performance suite, could ask how you might contribute to the perf suite to get some visibility into the merge implementation.
https://github.com/bestiejs/lodash/blob/master/lodash.js#L1677-1738
Edit: As an aside, I wouldn't prematurely optimize. I would see if this is actually a problem in your use case and then move on to actual data. I would look at something like: https://github.com/felixge/faster-than-c
Basic tenets:
Collect data
Analyze it
Find problems
Fix them
Repeat
He's got tips on each of those.
If you don't use Lo-Dash, and just want a tool to merge two objects including their arrays, use deepmerge: https://github.com/nrf110/deepmerge
npm install deepmerge

Categories