Using an asterisk* as a key in an object - javascript

I'm getting an error trying to use an asterisk as a key reference of an object. I've tried formatting different ways, but always get the same error:
SyntaxError: missing name after . operator
Here is my code with an object rendered from the wikipedia api...
The line in question is:
console.log(shortcut.langlinks[index].*);
var wp = {
"query":{
"pages":{
"3823":{
"pageid":3823,
"ns":0,
"title":"Binary",
"extract":"<p><b>Binary</b> means <i>composed of two pieces or two parts</i> and may refer to:</p>\n\n",
"links":[{
"ns":0,"title":"Binary-coded decimal"},{
"ns":0,"title":"Binary (Assemblage 23 song)"},{
"ns":0,"title":"Binary code"}],
"langlinks":[{
"lang":"de","*":"Bin\u00e4r"},{
"lang":"fr","*":"Binaire"},{
"lang":"ur","*":"\u062a\u062b\u0646\u06cc\u06c1"}]
}
}
}
};
var page_key = Object.keys( wp['query']['pages'])[0];
var shortcut = wp['query']['pages'][page_key];
function translation() {
if (shortcut.langlinks.length > 0){
for (var index in shortcut.langlinks){
if (shortcut.langlinks[index].lang == 'de'){
console.log(shortcut.langlinks[index].*);
}
}
} else {
console.log("There are no language links.");
}
}
How do I format my code to get the asterisk to display like a key value?
Thanks.

You can use brackets as well:
shortcut.langlinks[index]['*']

When you want to access a property whose name is also a valid name for an identifier you can use the dot syntax: shortcut.langlinks (langlinks is a valid identifier name).
When the property name is not a valid identifier name, you must use the angle bracket syntax instead: langlinks[index]["*"] (* is not a valid identifier name because it does not start with "$", "_", or any Unicode character that is classed as a letter).

You can use:
console.log(shortcut.langlinks[index]['*']);

Related

.toLowerCase() / .toUpperCase() not working

I'm trying to get better at javascript through codewars.com katas, and I came across an exercice in which things like element[i]=element[i].toLowerCase() doesn't change anything at all.
I would like to have some help with my code, here is the exercice's instructions followed by my code:
(Please note that I'm not very experienced with JS so the code may not be perfect at all)
A string is considered to be in title case if each word in the string
is either:
(a) capitalised (that is, only the first letter of the word
is in upper case) or
(b) considered to be an exception and put entirely into lower case unless it is the first word, which is always capitalised.
Write a function that will convert a string into title case, given an optional list of exceptions (minor words). The list of minor words will be given as a string with each word separated by a space.
Your function should ignore the case of the minor words string -- it should behave in the same way even if the case of the minor word string is changed.
Arguments:
First argument (required): the original string to be converted.
Second argument (optional): space-delimited list of minor words that must always be lowercase except for the first word in the string. The JavaScript/CoffeeScript tests will pass undefined when this argument is unused.
function titleCase(title, minorWords) {
if(title.length==0){return ""}
var titlesplit = title.split(" ")
if(minorWords){
minorWords=minorWords.split(" ")
}
var solutionstring = ""
titlesplit.forEach(element => myfunction(element,minorWords))
solutionstring[0] = solutionstring[0].toUpperCase()
return solutionstring
function myfunction(element,minorWords){
var elementlength= element.length
var i=0
if(minorWords && minorWords.includes(element)){
for(i;i<elementlength;i++){
element[i]=element[i].toLowerCase()
}
}else {
for(i;i<elementlength;i++){
if(i==0){element[i]=element[i].toUpperCase()}
else{element[i]=element[i].toLowerCase()}
}
}
if(solutionstring.length==0){solutionstring=solutionstring+element}else{solutionstring=solutionstring+" "+element}
return
}
}
As pointed out in comments, Strings are immutable in JavaScript.
Additionally, for searching use Maps instead of includes.
Likewise you can see what Set in JavaScript is and easily use Set here.
Added comments for you better understanding.
function titleCase(title, minorWords) {
// Use === for comparison
// Prefer using curly braces even for single statements
if (title.length === 0) {
return "";
}
var titlesplit = title.split(" ");
// Maps/Objects give O(1) search compared to arrays O(n)
// Key,value pairs - similar to dictionary
var minorWordsMap = {};
minorWords.split(" ").forEach(i => minorWordsMap[i.toLowerCase()] = true);
var finalWords = titlesplit.map((element, index) => convertCase(element, index));
finalWords[0] = toPascalCase(finalWords[0]);
return finalWords.join(" ");
function toPascalCase(s) {
s = s.split("");
s[0] = s[0].toUpperCase();
return s.join("");
}
function convertCase(element, index) {
const lElement = element.toLowerCase();
// If element is part of exception words, ignore
if(index !== 0 && minorWordsMap[lElement]) {
return element;
}
// If first element or not in exception list, send Title case
return toPascalCase(lElement);
}
}

eval() triggers Unexpected number when part of string passed into it has decimal

The below works perfectly until a key is sent to it with a decimal in it. Then it triggers an "Unexpected number". I can think of some work arounds that have to do with modifying the keys in the object sent from the database, but want to figure out why this triggers an error first.
What is happening in the below:
A number of percentiles are sent from the FE by the user (e.g., 5th, 15th, 35th, 62.5th, etc.) as an object (e.g. incP1: 5th, incP2: 15th, etc.) which are then mapped.
If the key starts with inc it does a certain set of logic.
It constructs a string (fieldStr) that corresponds with a key in the cr object which is basically the actual values of the percentiles the user requested.
In this case it would construct something like cr.TestInc15
The let fieldObj = eval(fieldStr) then returns the value from cr. of the key that was constructed.
Hopefully that makes sense, but that is why I am using eval() because I can't get the value from just the key as string otherwise. It works fine until it hits something like the 62.5th percentile where the key would be constructed as cr.TestInc62.5 which definitely has a value in cr. as I can console.log it out.
renderData(percentiles, cr, varName) {
return (
_.map(
_.pickBy(percentiles, function (value, key) {
return _.startsWith(key, 'inc')
}), p => {
let fieldStr = 'cr.' + varName + 'Inc' +
(p == 'n' ? 'N' :
(p == 50 ? 'Median' : p
));
// a bunch of junk after this, but error stops it here
let fieldObj = eval(
fieldStr
);
}
)
)
}
Of course you can get the value with a string, you can access an object property without using eval even in your case of having dots as part of property names.
It's called bracket notation
See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors
var cr = { "TestInc62.5": "Val123" }
console.log(cr["TestInc62.5"]);

Javascript Object negative number

Create object adjustementType inside script tag in MVC 5 partial view.
<script type="text/javascript">
var adjustementType = { -1:'Rate Decrease', 1: 'Rate Increase' };
</script>
but getting following error "Expected identifier, string or number" . The error is thrown on area -1 & 1 field.
You cannot use strings with spaces because you are defining variables and you also should turn type around like this:
var adjustementType = { RateDecrease: -1, RateIncrease: 1 };
alert(adjustementType.RateDecrease); //-1
This is because you are actually defining enums.
EDIT: You can use strings with spaces too but then you are dealing with them like arrays. But I think this doesn't make any sense.
var enumtype = { "-1": "Rate Decrease", "1" : "Rate Increase"};
alert(enumtype["1"]); //Rate Increase
alert(enumtype["-1"]); //Rate Decrease
Since -1 is not valid identifier you need to take such keys into quotes when you define an object properties:
var adjustementType = { '-1': 'Rate Decrease', 1: 'Rate Increase' };
then you will be able to access it using bracket notation:
alert(adjustementType[-1]);

Parsing javascript array with multiple keys

Hi I need to parse a JavaScript array that has multiple keys in it. Here is an example of what I need to do. Any help is appreciated.
[
week1{
Meth:100,
Marijuana:122,
pDrugs:12,
},
week2{
Meth:15,
Marijuana:30,
pDrugs:22,
},
]
I need this to be broken into separate arrays based on if it is week1 or week2. Thanks again in advance.
The end needs to be like this.
week1 = ["Meth:100,Marijuana:122,pDrugs12"] etc.
Your JSON has severe improper formatting. If it's already an object (which I'm guessing it isn't -- otherwise, you'd be getting unexpected token errors in your browser console), then change the brackets to braces, remove the trailing commas, and add colons after the object items that don't have them (after week1 and week2).
If what you have is a string (obtained from XHR or similar), you'll have to do all the changes mentioned above, as well as enclosing each object item within quotation marks. It should look like:
{
"week1": {
"Meth":100,
"Marijuana":122,
"pDrugs":12
},
"week2": {
"Meth":15,
"Marijuana":30,
"pDrugs":22
}
}
Whatever you're dealing with that's serving such horribly invalid JSON ought to be taken out back and shot. Be that as it may, this'll require some serious string manipulation. You're going to have to do some thorough massaging with String.replace() and some regular expressions.
After you get the JSON valid, then you can get week1 with JSON.parse and drilling down the resulting object.
function log(what) { document.getElementById('out').value += what + '\n------------------\n'; }
var tree = '[ week1{ Meth:100, Marijuana:122, pDrugs:12, }, week2{ Meth:15, Marijuana:30, pDrugs:22, }, ]';
// string is raw
log(tree);
tree = tree.replace(
'/\r?\n/g', '' // remove line breaks to make further regexps easier
).replace(
'[','{' // replace [ with {
).replace(
']','}' // replace ] with }
).replace(
/\w+(?=[\{\:])/g, // add quotes to object items
function($1) { return '"'+$1+'"'; } // using a lambda function
).replace(
/"\{/g, '": {' // add colon after object items
).replace(
/,(?=\s*\})/g, '' // remove trailing commas
);
// string has been fixed
log(tree);
var obj = JSON.parse(tree);
log('obj.week1 = ' + JSON.stringify(obj.week1));
log('obj.week1.Meth = ' + obj.week1.Meth);
#out {
width: 100%;
height: 170px;
}
<textarea id="out"></textarea>

Detect difference between & and %26 in location.hash

Analyzing the location.hash with this simple javascript code:
<script type="text/javascript">alert(location.hash);</script>
I have a difficult time separating out GET variables that contain a & (encoded as %26) and a & used to separate variables.
Example one:
code=php&age=15d
Example two:
code=php%20%26%20code&age=15d
As you can see, example 1 has no problems, but getting javascript to know that "code=php & code" in example two is beyond my abilities:
(Note: I'm not really using these variable names, and changing them to something else will only work so long as a search term does not match a search key, so I wouldn't consider that a valid solution.)
There is no difference between %26 and & in a fragment identifier (‘hash’). ‘&’ is only a reserved character with special meaning in a query (‘search’) segment of a URI. Escaping ‘&’ to ‘%26’ need be given no more application-level visibility than escaping ‘a’ to ‘%61’.
Since there is no standard encoding scheme for hiding structured data within a fragment identifier, you could make your own. For example, use ‘+XX’ hex-encoding to encode a character in a component:
hxxp://www.example.com/page#code=php+20+2B+20php&age=15d
function encodeHashComponent(x) {
return encodeURIComponent(x).split('%').join('+');
}
function decodeHashComponent(x) {
return decodeURIComponent(x.split('+').join('%'));
}
function getHashParameters() {
var parts= location.hash.substring(1).split('&');
var pars= {};
for (var i= parts.length; i-->0;) {
var kv= parts[i].split('=');
var k= kv[0];
var v= kv.slice(1).join('=');
pars[decodeHashComponent(k)]= decodeHashComponent(v);
}
return pars;
}
Testing on Firefox 3.1, it looks as if the browser converts hex codes to the appropriate characters when populating the location.hash variable, so there is no way JavaScript can know how the original was a single character or a hex code.
If you're trying to encode a character like & inside of your hash variables, I would suggest replacing it with another string.
You can also parse the string in weird ways, like (JS 1.6 here):
function pairs(xs) {
return xs.length > 1 ? [[xs[0], xs[1]]].concat(pairs(xs.slice(2))) : []
}
function union(xss) {
return xss.length == 0 ? [] : xss[0].concat(union(xss.slice(1)));
}
function splitOnLast(s, sub) {
return s.indexOf(sub) == -1 ? [s] :
[s.substr(0, s.lastIndexOf(sub)),
s.substr(s.lastIndexOf(sub) + sub.length)];
}
function objFromPairs(ps) {
var o = {};
for (var i = 0; i < ps.length; i++) {
o[ps[i][0]] = ps[i][1];
}
return o;
}
function parseHash(hash) {
return objFromPairs(
pairs(
union(
location.hash
.substr(1)
.split("=")
.map(
function (s) splitOnLast(s, '&')))))
}
>>> location.hash
"#code=php & code&age=15d"
>>> parseHash(location.hash)
{ "code": "php & code", "age": "15d" }
Just do the same as you do with the first example, but after you have split on the & then call unescape() to convert the %26 to & and the %20 to a space.
Edit:
Looks like I'm a bit out of date and you should be using decodeURIComponent() now, though I don't see any clear explanation on what it does differently to unescape(), apart from a suggestion that it doesn't handle Unicode properly.
This worked fine for me:
var hash = [];
if (location.hash) {
hash = location.href.split('#')[1].split('&');
}

Categories

Resources