How to search in complex javaScript array object - javascript

I am a bit confused. I have the following code in the directive:
NavTabsDirective.prototype.addPane = function (pane) {
if (!_.isObject(pane) || "Pane" !== pane.constructor.name) {
throw new TypeError("pane must be an instance of Pane");
}
if (_.isUndefined(this.FirstPane)) {
this.FirstPane = pane;
}
this.Panes[pane.name] = pane;
};
when I look in the debugger at the this.Panes array, I see something like:
this.Panes[name1] = paneObject -- with properties
this.Panes[name2] = paneObject -- with its properties
I want to understand how to search this array. Say, this is my code:
let invalid = (_.findIndex(this.Panes, { 'isValid': false })>=0);
which I commented out as it could not find a pane where isValid is false although I can see such pane in that array.
So, my confusion comes from the fact that the Panes array object has names to access each pane object and so I don't know how to properly search it. How would I check for invalid among the panes?

Unless pane.name is a number the panes in this.panes is not an array, it's an object, you can use it's keys and reduce it to a value:
const result = Object.keys(this.Panes).reduce(
(all,key)=>all && this.Panes[key].isValid,
true
)

Figured out a solution after checking few threads here:
for (let pane in this.Panes) {
if (this.Panes[pane].isValid === false) {
invalid = true;
break;
}
}
It works nicely.

var Panes = ["Hello","World"];
var PanesLength = Panes.length;
for (var i = 0; i < PanesLength; i++) {
if(Panes[i] == "Hello"){
alert(Panes[i]);
}
}

Related

How to modify object in for loop? React Native

I am new in react native , I want to insert new value into every object of array.
I have successfully implemented the logic according to object value. Condition is working right, I have checked by console.log() the statement working right but when I print the my final output array the new value of every object is same, value not assign different in object according to condition.
Here is the code which I am using:-
var newOffers = [];
response.data.forEach((element) => {
for (let i = 0; i < element.frequency; i++) {
var offer = element;
if (offer.used == 0) {
offer.isAvailable = "true";
newOffers.push(offer);
} else {
if (offer.frequency - i <= offer.used) {
console.log("True calling", offer.frequency - i);
offer.isAvailable = "false";
newOffers.push(offer);
} else {
console.log("False calling", offer.frequency - i);
offer.isAvailable = "true";
newOffers.push(offer);
}
}
}
});
console.log("All offers ", newOffers);
I have assign "isAvailable" value "true" or "false" to offer object and all condition working perfectly but when I print the "newOffers" array after complete the loop process the all "isAvailable" values is "false"
What wrong with this code? can someone help me?
In javascript when you use = operator for the objects, it doesn't work like as you expect. You should change your code like this if you are familiar with ES6:
var offer = {...element}
or
var offer = Object.assign({}, element);
Read this

How to copy the values of an array (not pointing). Slice isn't working for me

I have a function that tries to systematically add arrays to another multidimensional array. At each step of the way the arrays being added are calculated correctly, however, these calculations change the previously entered values. I've tried using slice but I'm clearly doing it wrong :(.
Please see code below - it is the return posMatrix that is being affected.
function allPossibilities(hand) {
var startingHandLength = hand.length;
var potHand = Array.prototype.slice.call(hand);
var scores = new Array();
var posMatrix = new Array();
var nextCard = 1;
var progressStage = true;
var finished = false;
var shallowArr = new Array();
do {
scores = calculateScores(potHand);
var maxScore = Math.max.apply(null, scores)
shallowArr = potHand.slice();
if (maxScore>16.5)
{posMatrix.push([shallowArr,maxScore])
console.log(posMatrix);
debugger;
if (potHand.length !== startingHandLength)
{
do{
if(potHand[potHand.length-1][1] < 10)
{
potHand[potHand.length-1][1]++;
progressStage = true;
}
else {potHand.pop();
potHand[potHand.length-1][1]++;}
}
while(progressStage === false)
}
}
else
{
potHand.push(["Imaginary",1,"Imaginary"]);
}
progressStage=false;
if(potHand.length === startingHandLength)
{finished = true;}
}
while(finished === false);
return posMatrix;
}
If the starting hand > 16.5, the function works as none of the other code gets to run. But otherwise it does not. The final return should be an array where each element is looks like this: [[array],number]. The number seems to come out fine, but since it is not an object it is not affected. I would expect the [array]s to be different from one another, currently they are all the same.
Slice returns a shallow copy of array, since you have multidimensional array so you need to deep clone of array
JSON.parse(JSON.stringify(array))
Or you can use loadash cloneDeep
You made a shallow copy of hand (which, BTW, you should've included). With statements like this
potHand[potHand.length-1][1]++;
you're accessing and modifying elements of hand, too.
Here, potHand[potHand.length-1] is an object, and it's en element of hand (not a copy - the same element).

Arrays in arrays, length always is 0, json not working

I try to create arrays in arrays and then forward it to JSON.
First problem, when i try to use a lista.length or something, console always return 0. I tried to overpass this problem and create another array, but now I have problem with JSON - always return [] - empty lista array.
var lista = [];
var licz = [];
function ListujBledy(value, where) {
var checked = document.getElementById(value).checked;
var desc;
if (value == "blad-tab") {
desc = "Nieprzeźroczysta lista graczy.";
} else if (value == "blad-tab1") {
desc = "Brak listy graczy na początkowym zrzucie ekranu.";
} else if (value == "blad-tab2") {
desc = "Brak listy graczy na końcowym zrzucie ekranu.";
}
if (checked == true) {
if (lista[where] == undefined) {
var temp = [];
temp[value] = desc;
lista[where] = temp;
licz[where] = 1;
} else if (licz[where] == 1) {
var temp = lista[where];
temp[value] = desc;
lista[where] = temp;
licz[where] = 2;
} else if (licz[where] == 2) {
var temp = lista[where];
temp[value] = desc;
lista[where] = temp;
licz[where] = 3;
}
} else {
if (licz[where] == 1) {
delete lista[where];
licz[where] = 0;
} else if (licz[where] == 2) {
delete lista[where][value];
licz[where] = 1;
} else if (licz[where] == 3) {
delete lista[where][value];
licz[where] = 2;
}
}
console.log(lista.length);
console.log(lista);
console.log(JSON.stringify(lista));
console.log("---------------------------------------------------------");
}
Console log from browser:
I don't have more ideas, I can't use lista[0], lista[1] etc. everything must be functional. Eveyrthing is taken from variables but everywhere I was looking for information about it, everybody using numbers in key or permanent keys.
Editied version of code:
I know that checked could have been better done, so I corrected it here.
https://jsfiddle.net/5vdgLtue/1/
The main problem is that even if I do this https://jsfiddle.net/5vdgLtue/0/ the array returns this element, but the length function says it is 0.
It looks like you might be starting out with javascript. Keep in mind that you haven't actually called the function at any point in your code. Is that the case or are you not sharing the full code you have run?
There is only one condition in which the array 'lista' could gain value: if 'check'== true and 'where' == undefined.
In that scenario, you declare the array 'temp' and declare temp[value]= desc. However, if 'value' contains a value different than "blad-tab", "blad-tab1" or "blad-tab2", 'desc' remains empty therefore temp[value] has a name but no value. You are then assigning a named valueless item to lista[where] which would explain why your console displays content but no length. btw, this would be easier if you named your variable something other than 'value' .
Problem is your selector points to the parent element. In jquery you could do this less code but assuming you're not using jQuery. Try something like:
function getDesc(chkboxName) {
var checkboxes = document.getElementsByName(chkboxName);
//or use getElementsbyClassName...
var checkboxesChecked = [];
// loop over them all
for (var i=0; i<checkboxes.length; i++) {
// And stick the checked ones onto an array...
if (checkboxes[i].checked) {
checkboxesChecked.push(checkboxes[i]);
}
}
for (var i=0; i<checkboxesChecked.length; i++) {
if (checkboxesChecked[i].value === "blad-tab") {
desc = "Nieprzeźroczysta lista graczy.";
} else if (checkboxesChecked[i].value === "blad-tab1") {
desc = "Brak listy graczy na początkowym zrzucie ekranu.";
} else if (checkboxesChecked[i].value === "blad-tab2") {
desc = "Brak listy graczy na końcowym zrzucie ekranu.";
}
}
return desc;
}
This should answer most of your questions.
In summary:
In javascript there are 2 types of arrays: standard arrays and associative arrays
[ ] - standard array - 0 based integer indexes only
{ } - associative array - javascript objects where keys can be any strings
What you are doing is using array in an associative manner. Basically, you are adding properties to your array objects, unlike a standard array where you would only assign values by zero-indexed numbers like temp[0]='something', lista[1]='some other thing' etc.
If you want the length of the key set of the array, then you can use Object.keys(lista).length. This should solve your problem.

Javascript if value is in array else in next array

I have found a few posts on here with similar questions but not entirely the same as what I am trying. I am currently using a simple if statement that checks the data the user enters then checks to see if it starts with a number of different values. I am doing this with the following:
var value = string;
var value = value.toLowerCase();
country = "NONE";
county = "NONE";
if (value.indexOf('ba1 ') == 0 || value.indexOf('ba2 ') == 0 || value.indexOf('ba3 ') == 0) { //CHECK AVON (MAINLAND UK) UK.AVON
country = "UK";
county = "UK.AVON";
} else if(value.indexOf('lu') == 0){//CHECK BEDFORDSHIRE (MAINLAND UK) UK.BEDS
country = "UK";
county = "UK.BEDS";
}
I have about 20-30 different if, else statements that are basically checking the post code entered and finding the county associated. However some of these if statements are incredibly long so I would like to store the values inside an array and then in the if statement simply check value.indexOf() for each of the array values.
So in the above example I would have an array as follows for the statement:
var avon = new Array('ba1 ','ba 2','ba3 ');
then inside the indexOf() use each value
Would this be possible with minimal script or am I going to need to make a function for this to work? I am ideally wanting to keep the array inside the if statement instead of querying for each array value.
You can use the some Array method (though you might need to shim it for legacy environments):
var value = string.toLowerCase(),
country = "NONE",
county = "NONE";
if (['ba1 ','ba 2','ba3 '].some(function(str) {
return value.slice(0, str.length) === str;
})) {
country = "UK";
county = "UK.AVON";
}
(using a more performant How to check if a string "StartsWith" another string? implementation also)
For an even shorter condition, you might also resort to regex (anchor and alternation):
if (/^ba(1 | 2|3 )/i.test(string)) { … }
No, it doesn’t exist, but you can make a function to do just that:
function containsAny(string, substrings) {
for(var i = 0; i < substrings.length; i++) {
if(string.indexOf(substrings[i]) !== -1) {
return true;
}
}
return false;
}
Alternatively, there’s a regular expression:
/ba[123] /.test(value)
My recomendation is to rethink your approach and use regular expressions instead of indexOf.
But if you really need it, you can use the following method:
function checkStart(value, acceptableStarts){
for (var i=0; i<acceptableStarts.length; i++) {
if (value.indexOf(acceptableStarts[i]) == 0) {
return true;
}
}
return false;
}
Your previous usage turns into:
if (checkStart(value, ['ba1', ba2 ', 'ba3'])) {
country = 'UK';
}
Even better you can generalize stuff, like this:
var countryPrefixes = {
'UK' : ['ba1','ba2 ', 'ba3'],
'FR' : ['fa2','fa2']
}
for (var key in countryPrefixes) {
if (checkStart(value, countryPrefixes[key]) {
country = key;
}
}
I'd forget using hard-coded logic for this, and just use data:
var countyMapping = {
'BA1': 'UK.AVON',
'BA2': 'UK.AVON',
'BA3': 'UK.AVON',
'LU': 'UK.BEDS',
...
};
Take successive characters off the right hand side of the postcode and do a trivial lookup in the table until you get a match. Four or so lines of code ought to do it:
function getCounty(str) {
while (str.length) {
var res = countyMapping[str];
if (res !== undefined) return res;
str = str.slice(0, -1);
}
}
I'd suggest normalising your strings first to ensure that the space between the two halves of the postcode is present and in the right place.
For extra bonus points, get the table out of a database so you don't have to modify your code when Scotland gets thrown out of leaves the UK ;-)

How to lessen this comparing loop

I need to find which id numbers are missing inside s.data compared to users.
Is there a better(smaller code) way to compare?
Thanks ;)
if(users.length != undefined)
{
for(y=0;y<users.length;y++)
{
var left = true;
for(y2=0;y2<s.data.length;y2++)
{
if(users[y].client_id==s.data[y2].client_id) {left = false;break;}
}
if(left) {users[y].ref.remove();delete users[y];}
}
}
else if(!jQuery.isEmptyObject(users))
{
var left = true;
for(y2=0;y2<s.data.length;y2++)
{
if(users.client_id==s.data[y2].client_id) {left = false;break;}
}
if(left) {users.ref.remove();users = {};}
}
Haven't checked if this is working code. :)
First, off, the 2nd branch appears to be nothing but a specialization of the first branch. You can use this to either make the "2nd" users = [users] (in which case users really means users and not a-user) and eliminates the top branch entirely, or remove the the logic into a function invoked per-user.
Now, to tackle the inner loop: What this is a 'map' and a 'contains'. Looking at it just in terms of a contains:
// Returns true if any item in data.client_id (an array)
// is that of user.client_id
function dataContains (user, data) {
for (var i = 0; i < data.length; i++) {
if (data[i].client_id == user.client_id) {
return true
}
}
return false
}
Now the code is reduced to:
for (each user) {
if (!dataContains(user, data)) {
// do something here
}
}
However, we could go one step further and use a generic 'contains' if we also have a 'map'. The final form is then:
var dataIds = map(data, function (x) { return x.client_id })
for (each user) {
if (!contains(user.client_id, dataIds)) {
..
}
}
Where the 'contains' is much more generalized:
// Returns true iff item is contained within arr
function contains (item, arr) {
// Just do what the comment documentation says
}
If you are using jQuery you already have handy functions:
'contains' - inArray, and a "sorta" 'map' - map. However, be warned! The jQuery 'map' is really a flat-map and was given an incorrect name and incomplete documentation!
I believe ECMAScript ED5 has these functions standard.
Also, you could invert the client_id's in the data to object keys and simply test for key existence, which is O(1) vs. O(n) iff the look-up is built once (or at least much, much less than it's used) and so it may be "theoretically" better. The size of n makes a large difference if it will actually matter, if at all. In this case it's likely the look-up could be built incrementally and saved between times this code is executed.
var existingIds = {}
for (var i = 0; i < data.length; i++) {
existingIds[data[i].client_id] = true
}
for (each user) {
if (!existingIds[user.client_id]) {
..
}
}

Categories