I have an array that keep changing with the user input.
for example:
user = ['a','b',['c','d'],'e',['f','g',['h','i'],'j']]
I also have a pointer to point where to make a change.
pointer = [1] change value at user[1]
pointer = [2,1] change value at user[2][1]
pointer = [4,2,2] change value at user[4][2][2]
Dimension is mostly not the same and can be more than 10.
Now I'm making a string then eval.
Can I write a function without using eval?
Use lodash's _.set!
_.set(user, [4,2,1], '!')
Or, if you don't want lodash, you can implement this one yourself.
function setDeep(obj, path, val) {
if (path.length === 1)
obj[path[0]] = val;
else
setDeep(obj[path.shift()], path, val)
}
// then use: setDeep(user, [4,2,1], 'something').
Note that this version will throw if the specified key doesn't exist. This is also not a good example of clarity and maintainability, so you'll need to improve it, but it's a good starting point - it does what you want.
If you neet to get instead of set - use lodash's _.get or implement it yourself, it would be very similar to my setDeep.
I assume that the user's input is a string and not an array like in your example, because you mentioned eval, otherwise it's a completely different approach.
var user = "['a','b',[4,'d'],'e',['f','g',['h','i'],'j']]";
JSON.parse(user.replace(/'/g, "\""));
Related
Example:
When I check a variable containing this value [""] it returns false.
var th=[]
th.push("");
if($("#multiselect").val()==th)
It returns always false.
Thank you.
Edit 1:
changed Var to var. It was a typo.
Edit 2:
Actually, the problem I faced was I was trying to get the value from a multi-select input. The multi-select input sometimes returns values as [""] even I haven't selected any values basically it's a plugin. So I was confused and I thought [""] is a fixed primitive value like 1, 10, "bla blah",.. So I tried to compare it with the same array as the right-hand side of the '=' operator.
It was stupid. Now I posted the solution to my problem and I explained my stupidity.
there are two things:
Change Var to var
You can use includes method of Array as:
var th = [] <==== chnage Var to var
th.push("");
if(th.includes($("#multiselect").val())) { <=== you can use includes method of array
// DO whatever you want
}
Make sure var is lowercased.
You are accessing th as an array, so you’ll need to specify the index of the value you are checking: th[0]
Use triple equals, too: .val()===th[0]
Double check the jquery docs if you’re still running into trouble.
Happy coding!
A couple of things to consider:
You have a typo in the code above; var is valid; Var is invalid.
Browser will aptly complain to solve this typo.
You are comparing an array to DOM value; this will always be false.
DOM is a costly process. Unless the value associated is dynamic, its better to read once, store value into a variable and continue processing instead of reading from DOM always.
You could choose to try something on these lines:
let arr = [1,2,3,4];
let domValue = $("#multiselect").val();
arr.push(5);
arr.map((el, ix) => {
if el === domValue return true; //or choose to do something else here.
});
var th=[]; //It is var not Var
th.push("");
if($("#multiselect").val()==th[0]) // change th to th[0]
I am unable to comment so having to use an answer for now. Are you trying to check if an array has any values? If so you can use
if(th.length){
// do something
}
If you want to check a normal variable for empty string you can simply use
if(th == “”){
//do something
}
I found the solution after a couple of days when I posted this question. Now I can feel how stupid this question was.
Anyway, I'm answering this question so it might help others.
Answer to my question:
When two non-primitive datatype objects(which is the Array here) are compared using an assignment operator, it compares its reference of the object. So the object creation of both arrays would be different. If I want to check the array has [""] value, I should do something like the below.
function isArrValEmptyCheck(value) {
return !value || !(value instanceof Array) || value.length == 0 || value.length == 1 && value[0] == '';
}
console.log(isArrValEmptyCheck([""]));//returns true
console.log(isArrValEmptyCheck(["value1"]));//returns false
Sorry for the late response. Thanks to everyone who tried to help me.
JSON files are compromised of a series of key's and values. I know the potential key's in a given JSON, but not whether or not they have corresponding non-empty values. I have loaded the JSON file into an object called JSON. I want to find the first of several possible key's with a value and then assign that value to a variable. When I say "first" I mean "first" according to a priority list that is not related to the structure of the JSON:
I could do the following and it works:
if(json.age)
myValue = json.age;
else if(json.classYear)
myValue = json.classYear;
else if(json.seniority)
myValue = json.seniority
else
myValue = false;
This works but sucks for several reasons:
It is slow to write
It is annoying to rewrite the key value name each twice in each row
It is a little hard to read
It is very difficult to reason with programatically. I don't have a use case that requires this, but I can imagine wanting to arbitrarily change the order of priority from within my code.
While not terribly slow to process, I can imagine that some other approach may compute faster.
These reasons lead me to believe that the method listed above is not ideal. Is there some other pattern that would be better?
(Note: I recognize that this question borders on a "how best to" as opposed to "how to" phrasing. I know SO is not wild about that sort of question and I don't mean my question to be interpreted as such. Rather, my question should be interpreted as asking, "is there some design pattern that is particularly suited for the problem describe above?)
(Note: I will only accept a vanilla answer, but feel free to provide other answers if you believe they will be helpful).
You could use short-circuit evaluation. You'll still have to write out all of the property names, but I'm not sure there's a way to accomplish this task without doing that.
const myValue = json.age || json.classYear || json.senority || false;
Okay, so if you have a one-dimensional hash table and an array for the priority of keys, then you can use an algorithm like this to select the first one available:
function grab(hash, keyPriority) {
var value;
keyPriority.some(function (key) {
if (hash.hasOwnProperty(key)) { // check if the property exists
value = hash[key];
return true; // break out of loop
}
});
return value;
}
usage:
grab({ c: 3, d: 4 }, ['a', 'b', 'c', 'd']) // 3
You can modify this to work by truthy values, or undefined/null by changing hash.hasOwnProperty(key) to hash[key] or hash[key] != null respectively.
If you are fine with using a bit of JQuery then the following code snippet should do the job I guess.
$.each(JSONObj, function(key, value){
if (!(value === "" || value === null)){
myValue = value;
return false; //to break the loop once a valid value is found
}
});
This will assign the first valid value to your variable myValue and will also exit the loop once a valid value is found.
I have a group of strings in Javascript and I need to write a function that detects if another specific string belongs to this group or not.
What is the fastest way to achieve this? Is it alright to put the group of values into an array, and then write a function that searches through the array?
I think if I keep the values sorted and do a binary search, it should work fast enough. Or is there some other smart way of doing this, which can work faster?
Use a hash table, and do this:
// Initialise the set
mySet = {};
// Add to the set
mySet["some string value"] = true;
...
// Test if a value is in the set:
if (testValue in mySet) {
alert(testValue + " is in the set");
} else {
alert(testValue + " is not in the set");
}
You can use an object like so:
// prepare a mock-up object
setOfValues = {};
for (var i = 0; i < 100; i++)
setOfValues["example value " + i] = true;
// check for existence
if (setOfValues["example value 99"]); // true
if (setOfValues["example value 101"]); // undefined, essentially: false
This takes advantage of the fact that objects are implemented as associative arrays. How fast that is depends on your data and the JavaScript engine implementation, but you can do some performance testing easily to compare against other variants of doing it.
If a value can occur more than once in your set and the "how often" is important to you, you can also use an incrementing number in place of the boolean I used for my example.
A comment to the above mentioned hash solutions.
Actually the {} creates an object (also mentioned above) which can lead to some side-effects.
One of them is that your "hash" is already pre-populated with the default object methods.
So "toString" in setOfValues will be true (at least in Firefox).
You can prepend another character e.g. "." to your strings to work around this problem or use the Hash object provided by the "prototype" library.
Stumbled across this and realized the answers are out of date. In this day and age, you should not be implementing sets using hashtables except in corner cases. You should use sets.
For example:
> let set = new Set();
> set.add('red')
> set.has('red')
true
> set.delete('red')
true
> set.has('red')
false
Refer to this SO post for more examples and discussion: Ways to create a Set in JavaScript?
A possible way, particularly efficient if the set is immutable, but is still usable with a variable set:
var haystack = "monday tuesday wednesday thursday friday saturday sunday";
var needle = "Friday";
if (haystack.indexOf(needle.toLowerCase()) >= 0) alert("Found!");
Of course, you might need to change the separator depending on the strings you have to put there...
A more robust variant can include bounds to ensure neither "day wed" nor "day" can match positively:
var haystack = "!monday!tuesday!wednesday!thursday!friday!saturday!sunday!";
var needle = "Friday";
if (haystack.indexOf('!' + needle.toLowerCase() + '!') >= 0) alert("Found!");
Might be not needed if the input is sure (eg. out of database, etc.).
I used that in a Greasemonkey script, with the advantage of using the haystack directly out of GM's storage.
Using a hash table might be a quicker option.
Whatever option you go for its definitely worth testing out its performance against the alternatives you consider.
Depends on how much values there are.
If there are a few values (less than 10 to 50), searching through the array may be ok. A hash table might be overkill.
If you have lots of values, a hash table is the best option. It requires less work than sorting the values and doing a binary search.
I know it is an old post. But to detect if a value is in a set of values we can manipulate through array indexOf() which searches and detects the present of the value
var myString="this is my large string set";
var myStr=myString.split(' ');
console.log('myStr contains "my" = '+ (myStr.indexOf('my')>=0));
console.log('myStr contains "your" = '+ (myStr.indexOf('your')>=0));
console.log('integer example : [1, 2, 5, 3] contains 5 = '+ ([1, 2, 5, 3].indexOf(5)>=0));
You can use ES6 includes.
var string = "The quick brown fox jumps over the lazy dog.",
substring = "lazy dog";
console.log(string.includes(substring));
I'm creating a few specific functions for a compiler I'm working on, But certain restrictions within the compiler's nature will prevent me from using native JavaScript methods like Array.prototype.pop() to perform array pops...
So I decided to try and write some rudimentary pseudo-code to try and mimic the process, and then base my final function off the pseudo-code... But my tests seem to fail... based on the compiler's current behavior, it will only allow me to use array.length, array element assignments and that's about it... My code is below...
pop2 = function(arr) {
if(arr.length>0){
for(var w=undefined,x=[],y=0,z=arr.length;y<=z;y++){
y+1<z?(x[y]=arr[y]):(w=arr[y],arr=x);
}
}
return w;
}
Arr = [-1,0,1,2];
// Testing...
console.log(pop2(Arr)); // undefined... should be 2
console.log(Arr); // [-1,0,1,2]... should be [-1,0,1]
I'm trying to mimic the nature of the pop function but can't seem to put my finger on what's causing the function to still provide undefined and the original array... undefined should only return if an initial empty array is sent, just like you would expect with a [].pop() call...
Anyone have any clues as to how I can tailor this code to mimic the pop correctly?
And while I have heard that arr.splice(array.length-1,1)[0]; may work... the compiler is currently not capable of determining splice or similar methods... Is it possible to do it using a variation of my code?
Thanks in advance...
You're really over-thinking [].pop(). As defined in the specs, the process for [].pop() is:
Get the length of the array
If the length is 0
return undefined
If length is more than 0
Get the item at length - 1
Reduce array.length by 1
Return item.
(... plus a few things that the JavaScript engine needs to do behind the scenes like call ToObject on the array or ensure the length is an unsigned 32-bit integer.)
This can be done with a function as simple as the one below, there's not even a need for a loop.
function pop(array) {
var length = array.length,
item;
if (length > 0) {
item = array[length - 1];
array.length -= 1;
}
return item;
}
Edit
I'm assuming that the issue with the compiler is that Array.prototype.pop isn't understood at all. Re-reading your post, it looks like arrays have a pop method, but the compiler can't work out whether the variable is an array or not. In that case, an even simpler version of this function would be this:
function pop(array) {
return Array.prototype.pop.call(array);
}
Try that first as it'll be slightly faster and more robust, if it works. It's also the pattern for any other array method that you may need to use.
With this modification, it works:
http://jsfiddle.net/vxxfxvpL/1/
pop2 = function(arr) {
if(arr.length>0){
for(var w=undefined,x=[],y=0,z=arr.length;y<=z;y++){
if(y+1<z) {
(x[y]=arr[y]);
} else {
(w=arr[y],arr=x);
break;
}
}
}
return w;
}
Arr = [-1,0,1,2];
// Testing...
console.log(pop2(Arr)); // 2
The problem now is to remove the last element. You should construct the original array again without last element. You will have problems with this because you can't modify the original array. That's why this tasks are maded with prototype (Array.prototype.pop2 maybe can help you)
I've such an input array that every element of the array is a dictionary {x:a_int, y:a_int}. Now I need to extract all y values and create a new array, so that it can be used to calculate the maximum of all y-values. Here is my current code:
var inputArray = [{x:1,y:100},{x:2,y:101},{x:3,y:103}];
function extractY(data) {
var result = [];
data.forEach(function (item) {
result.push(item.y);
});
return result;
}
// Test code
var yArray = extractY(inputArray);
console.log(Math.max.apply(Math, yArray));
I want to make code shorter. As I'm new to javascript, I'd like to know, if it possible to shorten the function extractY(). My imagination is to have a transformation function. The code should not rely on jQuery and does not have to consider old browser compatibility.
You can simply use Array.prototype.map, which will create a new Array with the values returned by the function passed to it, like this
function extractY(data) {
return data.map(function (item) {
return item.y;
});
}
Or you can simply write the same as
console.log(Math.max.apply(Math, inputArray.map(function(item) {
return item.y;
})));
Using reduce, you can get the maximum y value directly:
inputArray.reduce(function(prev, curr) {
return prev.y > curr.y ? prev : curr;
}).y
With underscore:
_.max(_.pick(inputArray, 'y'))
With d3:
d3.max(inputArray, function(d) { return d.y; })
Note in response to #AmitJoki's comment: Yes, I know this question was not tagged underscore. If you don't want to use underscore, feel free to ignore this answer. Having said that, underscore is a highly useful utility toolbelt that is perfect for solving problems such as this, among many other things. It's exhaustively tested and robust and efficient and handles all the edge cases correctly. Unlike certain other bloated libraries, it's quite lightweight and is well worth learning.
I doubt if it falls within the realm of common sense to imply that the failure to mark a question "underscore" means that underscore-based answers are somehow not acceptable, considering that it's easy to imagine that in many cases the OP may not even be aware of that option and might welcome a suggestion about how to write more compact code, while learning a useful tool in the process.