Is there a way to get the dataset's multiple values? - javascript

<input type="file" data-custom="file" data-custom-icons="i-file i-upload" />
I wanna get the value of data-custom-icons, but separate them with space.
// PREFERRED OUTPUT: ["i-file", "i-upload"]
I know how to basically get the value itself and tried to make them in an array via Array.from() like I did with the classList. But when I do it for that dataset my output is per letter object.
var icons = el.dataset.customIcons;
console.log(icons);
var ic = Array.from(icons);
console.log(ic);
// WRONG OUTPUT: ["i", "-", "f", "i", "l", "e", " ", "i", "-", "u", "p", "l", "o", "a", "d"]
// Converting the classList in to an object
var cl = Array.from(el.classList);
console.log(cl);
OUTPUT: ["btn","btn-primary"]
Was there a reason why the dataset is behaving that way?

In this case, you need to use the split() method with the desired delimiter:
console.log( document.querySelector('input[type="file"]').dataset.customIcons.split(/\s+/) );
<input type="file" data-custom="file" data-custom-icons="i-file i-upload" />

Related

How to create a function to select specific array?

I am trying to create a function that is called by multiple different buttons, and that selects a specific array depending on which button called the function.
For example:
If a button with id="Anterior" called the function, the function selects array named plusAnterior:
var plusAnterior = ["p", "b", "t", "d", "ɸ", "β", "f", "v", "θ", "ð", "s", "z", "m", "n", "l", "ɬ", "r", "ɾ"];
var minusAnterior = ["c", "ɟ", "k", "g", "ʃ", "ʒ", "x", "ɣ", "ɲ", "ŋ", "j", "w", "ʡ", "h"];
var toAdd = [];
function addFeature(featureId) {
if (activeFeatures === 0) {
toAdd = // plusAnterior called here
}
}
The problem is, I cannot simply do toAdd = plusAnterior because I want my function to work for any button pressed. I thought of doing something like getElementById("plus" + featureId), but I can't since the arrays I'm trying to select are not in my HTML.
Thank you for any help.
In javascript, you can use an object almost as a key/value array.
var testObject = {
featureId_a: [1, 2, 3, 4, 5], // etc
featureId_b: [1, 2, 3, 4, 5] // etc
}
Then we can return it with your method like so...
function addFeature(featureId) {
return testObject[featureId];
}
I think this is what you mean. Otherwise, you could use a 2D array and select based on the index. But it depends on your data really the best option.
For brevity and some sanitization, you should, of course, check the object for the property.
if(testObject.hasOwnProperty(featureId)){
return testObject[featureId];
}

javascript - check if array contains any of another array of strings

strings_to_check = ["a", "b", "c"]
test_arrrays = [ [ "a", "c", "e", "g"], [ "v", "x", "y", "z"] ]
What is the right way to check if each array in test_arrays contains any of the strings in strings_to_check array - ie. a, b or c
I could do the following, but it has its downside that even if one of the strings is present, it still check's for the rest.
for(let i = 0; i < test_arrrays.length; i++){
for(let j = 0; j < strings_to_check.length; j++){
if(test_arrrays[i].indexOf(strings_to_check[j]) > -1) {
console.log("matched");
}
}
}
This can be much more simply done with higher order functions, instead of devolving to using for loops and a slew of indices.
We want to see if all test_arrrays elements meet some criteria, so we know we should use every:
test_arrrays.every(/* some criteria */);
Now we just have to find out what that criteria is. "contains any of the strings in strings_to_check" Sounds like we need to use some on test_array, to find out if any of its strings are contained in strings_to_check. So our "criteria" will be:
test_arrray => test_arrray.some(s => strings_to_check_set.includes(s))
putting it together, we get:
test_arrrays.every( test_arrray =>
test_arrray.some(s => strings_to_check_set.includes(s))
)
includes has linear time complexity, so we can improve this algorithm by using a Set, and replacing includes with has, which has constant time complexity., to obtain this final result:
strings_to_check = ["a", "b", "c"]
test_arrrays = [ [ "a", "c", "e", "g"], [ "v", "x", "y", "z"] ]
strings_to_check_set = new Set(strings_to_check)
test_arrrays.every(test_arrray =>
test_arrray.some(s => strings_to_check_set.has(s))
)
Assuming that you want to check if every array from test_arrays contains at least one element from the strings_to_check array, you could use mix of Array#every and Array#some functions.
var strings_to_check = ["a", "b", "c"],
test_arrrays = [ [ "a", "c", "e", "g"], [ "v", "x", "y", "z"] ],
res = test_arrrays.every(v => v.some(c => strings_to_check.indexOf(c) > -1));
console.log(res);
If you have multiple test_arrrays, it makes sense to convert the strings_to_check into a Set for constant time lookup. The overall time complexity then reduces from O(m n) to O(m + n log n) where n is the number of elements in strings_to_check and m is the total number of elements in all test_arrrays and O(n log n) is the Set setup time.
A generic check function would then look as follows:
// Check if each haystack contains at least one needle:
function check(needles, haystacks) {
needles = new Set(needles);
return haystacks.every(haystack => haystack.some(element => needles.has(element)));
}
// Example:
console.log(check(
["a", "b", "c"],
[["a", "c", "e", "g"], ["v", "x", "y", "z"]]
));
If you only need to match one string just add break just like this :
for(/*loop settings*/){
/*some code*/
for(/*loop settings*/){
/*some code*/
if(/*some conditional statement*/){
/*handling stuff*/
break;
}
}
}

Character Counter won't print all Characters

I am making a character counter as a hobby code. So far, it is working, but I have a glitch I can't seem to solve. When I write the terms "a,b,c", then it correctly writes a:1 b:1 c:1. But when I write "a,a,c,c", then it only writes a:2. I am not sure what's wrong. Here is the JavaScript portion of my code (myFunction is activated by a button, and testinput.value is the value of the textbox I am using):
function myFunction() {
var occurence = document.getElementById("testinput").value;
var cycleOne = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
"u", "v", "w", "x", "y", "z"
];
for (i = 0; i < 26; i++) {
var counter = new RegExp(cycleOne[i], 'g');
document.write(occurence.match(counter).length);
}
}
It is printing only 2 because, it is failing with an error, immediately after that.
Let's consider the case when the input is a,a,c,c.
In the first iteration of the loop, you will be matching against a and then it finds two matches and it prints it.
In the second iteration, you will be matching against b and it is not there in the string. So occurence.match(counter) will be returning null and you are trying to get the length property from null. That is why it is throwing the error
TypeError: Cannot read property 'length' of null
and stops execution.
To fix this, you need to check if it is not null, before proceeding, like this
var result = occurence.match(new RegExp(cycleOne[i], 'g'));
if (result !== null) {
console.log(result.length);
}

Javascript Nested Loop Matching, Combining, Replacing

I have two arrays:
arr1 = ["a", "b", "c", "d", "e", "f", "g"]
arr2 = ["z", "q", "a", "v", "y", "e"]
I want to produce a an array of results to be this:
results = ["aa", "b", "c", "d", "ee", "f", "g"]
Basically I want to push into a results array everything in order in arr1 and if it has a match combine with the matching key, if not still list the item from arr1. So the results array is every item in arr1 but if it matched anywhere in obj 2 take the matching key and combine it. Note: results[0] is arr1[0] + arr2[2] not arr1[0] + arr1[0]
My actual problem is more complex, but I think this is the best simplification I can deduce. I am looking for a nested loop (or any way that works) that would produce this. Any help would be greatly appreciated, I know I'm close but so far I have not been able to produce this, and have been pulling my hair out trying. Thank you!
Answer by Juhana:
var results = arr1.map(function (val) {
return val + (arr2.indexOf(val) > -1 ? val : '');
});

Array.sort on a string

Does anyone know why it's illegal to call Array.sort on a string?
[].sort.call("some string")
// "illegal access"
But calling Array.map, Array.reduce, or Array.filter is okay?
[].map.call("some string", function(x){
return String.fromCharCode(x.charCodeAt(0)+1);
});
// ["t", "p", "n", "f", "!", "t", "u", "s", "j", "o", "h"]
[].reduce.call("some string", function(a, b){
return (+a === a ? a : a.charCodeAt(0)) + b.charCodeAt(0);
})
// 1131
[].filter.call("some string", function(x){
return x.charCodeAt(0) > 110;
})
// ["s", "o", "s", "t", "r"]
Strings are immutable. You can't actually change a string; in particular, Array.prototype.sort would modify a string to be sorted, so you can't do that. You can only create a new, different string.
x = 'dcba';
// Create a character array from the string, sort that, then
// stick it back together.
y = x.split('').sort().join('');
Because strings are immutable.
The functions you mention that work return a new object, they don't update the string in place.
Of course it's easy to sort a string a little less directly:
var sorted = "some string".split("").sort().join("");

Categories