How would I change this code to a different format? (Javascript) - javascript

The code below is the code that I have written:
function singer(artist) {
var songs = [];
for(var i = 0; i < music.length;i++ ){
if(music[i].artist.indexOf(artist) > -1) {
songs.push(music[i].name);
}
}
return songs;
}
The code that I want to look similar to the function singer(artist) code is this:
const genreCount = () => {
const genres = music.reduce((result, cur) => {
cur.genres.forEach(g => {
if (result.hasOwnProperty(g)) {
result[g] += 1;
}
else
result[g] = 1;
});
return result;
}, {});
return genres;
}
I am unfamiliar with this type of format in Javascript, how would I change it so that const genreCount will look like function singer(artist).

This is what you will get if you want to change that function:
function genreCount() {
const genres = music.reduce(function(result, cur) {
cur.genres.forEach(function(g) {
if (result.hasOwnProperty(g)) {
result[g] += 1;
}
else
result[g] = 1;
});
return result;
}, {});
return genres;
}
or (if you want to assign that fucntion to a const anyway):
const genreCount = function() {
const genres = music.reduce(function(result, cur) {
cur.genres.forEach(function(g) {
if (result.hasOwnProperty(g)) {
result[g] += 1;
}
else
result[g] = 1;
});
return result;
}, {});
return genres;
}
You just should replace arrow functins with the regular function expressions. But I don't know why do you need that.

this style is called functional programming
const singer = artist => music.filter(m => artist.indexOf(m.artist) > -1).map(m => m.name)
here is a good interactive tutorial if you are interested
Functional Programming in Javascript
UPDATE:
oops, sorry for misunderstanding your questions
here is genreCount rewritten with for-loop:
function genreCount(){
const genres = {};
for(var i=0; i<music.length; i++){
var g = music[i]
if (genres.hasOwnProperty(g)) {
genres[g] += 1;
}
else{
genres[g] = 1;
}
}
return genres;
}

Related

rewrite an array of letters to numbers using dictionary

examples:
"heLLo" => 0.1.2.2.3
"javAscript" => 0.1.2.1.3.4.5.6.7.8
"hippopotomonstrosesQuippedaliophobia" => 0.1.2.2.3.2.3.4.3.5.3.6.7.4.8.3.7.9.7.10.11.1.2.2.9.12.13.14.1.3.2.0.3.15.1.13
my non-working code:
function wordPattern(word) {
var res = []
var dic = []
var count = 0
var pipa = word.toLowerCase().split("")
for (i=0;i<pipa.length;i++) {
if (!dic.includes(pipa[i])) {
dic.push({key: count, value: pipa[i]});
count ++
}
for (j=0;j<pipa.length;j++) {
res.push(dic.key[pipa[i]])
}
return res.join(".");
}
Thanks in advance
To associate characters to numbers, don't use an array, use an object:
function wordPattern(word) {
const numbersByChar = {};
let i = 0;
return [...word]
.map(char => numbersByChar[char] ?? (numbersByChar[char] = i++))
.join('.');
}
console.log(wordPattern('hello'));
console.log(wordPattern('hippopotomonstrosesquippedaliophobia'));
Or without the concise syntax that you might find more readable
function wordPattern(word) {
const numbersByChar = {};
let i = 0;
return Array.from(word)
.map((char) => {
if (numbersByChar[char] === undefined) {
numbersByChar[char] = i;
i++;
}
return numbersByChar[char];
})
.join('.');
}
console.log(wordPattern('hello'));
console.log(wordPattern('hippopotomonstrosesquippedaliophobia'));
hint 1 is that you can get a letter like: word[index]
so change your code to this:
function wordPattern(word) {
var res = []
var dic = []
var count = 0
for (i=0;i<word.length;i++) {
let dicItem = dic.find(x=>x.value==word[i]);
if(!dicItem) {
dic.push({key: count, value: word[i]});
res.push(count);
count ++;
}
else res.push(dicItem.key);
}
return res.join(".");
}

Is there a way to clean this code up? It functions, but it's hacked together and ugly

Looking for a cleaner way to write this for loop. I was going to use continue; and realized after the fact that .forEach doesn't like that syntax.
const findNoOptions = array => {
let str = "";
for (let i = 1; ; i += 1) {
str = "Z".repeat(i);
let found = false;
array.forEach(element => {
if (element.toUpperCase().includes(str)) {
found = true;
}
});
if (!found) {
break;
}
}
};
Maybe something like that
const findNoOptions = array => {
let str = "";
while(true) {
str += "Z";
let found = array.some(el => el.toUpperCase().includes(str))
if (!found) break;
}
};
Instead of using a break you could do
const findNoOptions = array => {
let str = "";
while(array.some(el => el.toUpperCase().includes(str))) {
str += "Z";
}
};

JavaScript Array Sort with Dynamic Column [duplicate]

This question already has answers here:
JavaScript property access: dot notation vs. brackets?
(17 answers)
Closed 3 years ago.
I have some code using JavaScript Array Sorting that works but seems to be really inefficient.
I have an array of objects defined as follows for example purposes
dummyData = [];
dummyData.push({ col01:"aa", col02:"ac", col03:"ab" });
dummyData.push({ col01:"ab", col02:"ab", col03:"ac" });
dummyData.push({ col01:"ac", col02:"aa", col03:"aa" });
Which I can then sort on col01 using a function like this
function f_sort_col01(dataArg) {
dataArg.sort(function(res01, res02) {
var arg01 = res01.col01.toLowerCase();
var arg02 = res02.col01.toLowerCase();
if(arg01 < arg02) { return -1; }
if(arg01 > arg02) { return 1; }
return 0;
});
return dataArg;
}
This works just fine but the problem is that when I need to sort on a different column I then have to create an entire new function like this
function f_sort_col02(dataArg) {
dataArg.sort(function(res01, res02) {
var arg01 = res01.col02.toLowerCase();
var arg02 = res02.col02.toLowerCase();
if(arg01 < arg02) { return -1; }
if(arg01 > arg02) { return 1; }
return 0;
});
return dataArg;
}
Which is pretty much the same thing only on a different column. I was wondering if it's possible to do something along the lines of this
function f_sort(dataArg, colName) {
dataArg.sort(function(res01, res02) {
var arg01 = res01.colName.toLowerCase();
var arg02 = res02.colName.toLowerCase();
if(arg01 < arg02) { return -1; }
if(arg01 > arg02) { return 1; }
return 0;
});
return dataArg;
}
So that the name of the column can be included in the parameters
Use square brackets like following
function f_sort(dataArg, colName) {
dataArg.sort(function(res01, res02) {
var arg01 = res01[colName].toLowerCase();
var arg02 = res02[colName].toLowerCase();
if(arg01 < arg02) { return -1; }
if(arg01 > arg02) { return 1; }
return 0;
});
return dataArg;
}
You coud reverse the approach by using a closure over the wanted key.
function sortBy(key) {
return function (a, b) {
return a[key].toLowerCase().localeCompare(b[key].toLowerCase());
};
}
var data = [{ col01: "aa", col02: "ac", col03: "ab" }, { col01: "ab", col02: "ab", col03: "ac" }, { col01: "ac", col02: "aa", col03: "aa" }];
console.log(data.sort(sortBy('col01')));
console.log(data.sort(sortBy('col02')));
console.log(data.sort(sortBy('col03')));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Use [colName] instead of .colName
function f_sort(dataArg, colName) {
dataArg.sort(function(res01, res02) {
var arg01 = res01[colName].toLowerCase();
var arg02 = res02[colName].toLowerCase();
if(arg01 < arg02) { return -1; }
if(arg01 > arg02) { return 1; }
return 0;
});
return dataArg;
}
Square bracket notation:
var arg01 = res01[colName].toLowerCase();
var arg02 = res02[colName].toLowerCase();

Getting nested obj value

Given the following obj:
var inputMapping = {
nonNestedItem: "someItem here",
sections: {
general: "Some general section information"
}
};
I'm writing a function to get that data by passing in a string "nonNestedItem" or in the nested case "sections.general". I'm having to use an eval and I was wondering if there was maybe a better way to do this.
Here is what I have so far and it works okay. But improve!
function getNode(name) {
var n = name.split(".");
if (n.length === 1) {
n = name[0];
} else {
var isValid = true,
evalStr = 'inputMapping';
for (var i=0;i<n.length;i++) {
evalStr += '["'+ n[i] +'"]';
if (eval(evalStr) === undefined) {
isValid = false;
break;
}
}
if (isValid) {
// Do something like return the value
}
}
}
Linky to Jsbin
You can use Array.prototype.reduce function like this
var accessString = "sections.general";
console.log(accessString.split(".").reduce(function(previous, current) {
return previous[current];
}, inputMapping));
Output
Some general section information
If your environment doesn't support reduce, you can use this recursive version
function getNestedItem(currentObject, listOfKeys) {
if (listOfKeys.length === 0 || !currentObject) {
return currentObject;
}
return getNestedItem(currentObject[listOfKeys[0]], listOfKeys.slice(1));
}
console.log(getNestedItem(inputMapping, "sections.general".split(".")));
You don't need to use eval() here. You can just use [] to get values from an object. Use a temp object to hold the current value, then update it each time you need the next key.
function getNode(mapping, name) {
var n = name.split(".");
if (n.length === 1) {
return mapping[name];
} else {
var tmp = mapping;
for (var i = 0; i < n.length; i++) {
tmp = tmp[n[i]];
}
return tmp;
}
}

how to get the querystring from a parent page?

i am using an iframe ipage in my parentpage. I would like to get the querystring in javascript of the parentpage?
I suggest to you to use my favourite function:
function getQueryString() {
var queryStringKeyValue = window.parent.location.search.replace('?', '').split('&');
var qsJsonObject = {};
if (queryStringKeyValue != '') {
for (i = 0; i < queryStringKeyValue.length; i++) {
qsJsonObject[queryStringKeyValue[i].split('=')[0]] = queryStringKeyValue[i].split('=')[1];
}
}
return qsJsonObject;
}
Just call it from the child window like this and act with the query string as an object.
For example if you have the query string ?name=stack and you want to get it, try:
getQueryString().name
This will return stack.
nice answer from #Marawan. - if it helps anyone...
I extended this to choose the target as a parameter (self / parent)
function getQueryString(target) {
if ( target == 'parent' ) {
var queryStringKeyValue = window.parent.location.search.replace('?', '').split('&');
}
else {
var queryStringKeyValue = window.location.search.replace('?', '').split('&');
}
var qsJsonObject = {};
if (queryStringKeyValue != '') {
for (i = 0; i < queryStringKeyValue.length; i++) {
qsJsonObject[queryStringKeyValue[i].split('=')[0]] = queryStringKeyValue[i].split('=')[1];
}
}
return qsJsonObject;
}
eg.
getQueryString('parent').id; // get iframe parent url ?id=foo
getQueryString().id; // get this url ?id=foo
ES6 implementation:
export const getQueryParameters = () => {
const queryStringKeyValue = window.parent.location.search.replace('?', '').split('&');
return queryStringKeyValue.reduce((acc, curr) => {
const [key,value] = curr.split('=')
return {
...acc,
[key]: value
}
}, {})
}
Usage:
getQueryParameters().name

Categories