function unusedDigits(...a){
return `0123456789`.split('').filter(
b => `${a}`.split('').indexOf(b) == -1
).join('');
}
document.write(unusedDigits(12345))
function unusedDigits(...a){
return `0123456789`.split('').filter(
b => `${a}`.split('').indexOf(b) == -1
).join('');
}
document.write(unusedDigits(12345))
What is
${a}
What is =>
And if someone could break down this code for me that would be amazing!
Share Improve this question edited Dec 30, 2015 at 15:05 Mogsdad 45.8k21 gold badges163 silver badges286 bronze badges asked Dec 30, 2015 at 13:19 Blue MoonBlue Moon 1891 silver badge11 bronze badges 1- They are called Arrow functions – ozil Commented Dec 30, 2015 at 13:22
3 Answers
Reset to default 111, What is ${a}
That's a substitution in a new JavaScript template string (added by ES2015). It swaps in the value of a
where it occurs. Any arbitrary expression is accepted.
2, what is =>
It's an ES2015 arrow function.
You didn't ask, but the ...
before the a
argument in the function declaration is a "rest operator" that says "give me the (rest of) the arguments supplied to the function as an array.
And if someone could break down this code for me that would be amazing!
It returns a string containing the digits that don't appear in the string form of any of the arguments passed to it:
- The
unusedDigits
function accepts any number of arguments, which it receives as an array accessed via thea
argument (thanks to the ES2015...
rest operator in the declaration of thea
argument). - It takes a string of the digits 0-9 and splits it to create an array (e.g.
['0', '1', ...]
). - Then it loops through that array via the
filter
function, getting a new array of only entries that thefilter
callback says should be kept. - The
filter
callback (an ES2015 arrow function) creates a string containing thea
array using an ES2015 template string. Since that involves callinga.toString()
implicitly, it ends up doinga.join(",")
implicitly (since that's whatArray#toString
does) and then checks if the digit being checked (b
) appears in the resulting string. (This is not very efficient; there's no reason to recreate the string each time, and no reason to use a template string here.) It returns a truthy value only if the digit wasn't in the string (indexOf
returned-1
). - Then it assembles a string at the end from the surviving digits and returns it.
Here's a more efficient version, FWIW: Live Copy on Babel's REPL
let unusedDigits = (function() {
const digits = [0,1,2,3,4,5,6,7,8,9];
return function unusedDigits(...a) {
let astring = String(a);
return digits.filter(b => astring.indexOf(b) == -1).join("");
};
})();
console.log(unusedDigits(12345));
And the same function in ES5:
var unusedDigits = (function() {
var digits = [0,1,2,3,4,5,6,7,8,9];
var slice = Array.prototype.slice;
return function unusedDigits() {
var astring = String(slice.call(arguments));
return digits.filter(function(b) { return astring.indexOf(b) == -1}).join("");
};
})();
(The slice
thing turns the pseudo-array arguments
into a true array.)
var unusedDigits = (function() {
var digits = [0,1,2,3,4,5,6,7,8,9];
var slice = Array.prototype.slice;
return function unusedDigits() {
var astring = String(slice.call(arguments));
return digits.filter(function(b) { return astring.indexOf(b) == -1}).join("");
};
})();
snippet.log(unusedDigits(12345));
<!-- Script provides the `snippet` object, see http://meta.stackexchange./a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
function unusedDigits(...a){
return `0123456789`.split('').filter(b=>`${a}`.split('').indexOf(b)==-1).join('');
}
alert(unusedDigits(12345))
...a in the first line is the rest operator - this will assign the arguments array to the variable a within the function body (so you don't have to deal with Array.prototype.slice.call(arguments) anymore. In this case var a = [12345]
'0123456789'.split('') will split out all of the digits from 0-9 into an array - which we then filter over.
b => ${a}
.split('').indexOf(b)==-1 is the predicate function for filter. => is known as 'fat arrow syntax' or 'arrow function'. This is ES6 - it's a shorthand syntax for functions that also binds the current 'this' binding to the function. If the body is on the same line, it will return the expression implicitly.
${a}
is the template string syntax - in this case coercing our arguments array [12345] into '12345', which we are then splitting to do an index of operation to see if the current digit (b) of 0-9 digits is in the split arguments array. At the end of it we return the result of filtering for all those digits 0-9 that are not in the arguments array, joined as a string - in this case '06789'.
Language features:
`${1}`;
// gives "1"
var v = 1; `${v}${v}`;
// gives "11"
x => x != "2";
// same as function (x) { return x != "2"; }
(x => x != "2")("1");
// gives true
((u, ...v) => v)(1, 2, 3);
// gives [2, 3]
String and Array methods:
"123".split("");
// gives ["1", "2", "3"]
["1", "2", "3"].join("");
// gives "123"
["1", "2", "3"].indexOf("2");
// gives 1
["1", "2", "3"].indexOf("4");
// gives -1
["1", "2", "3"].filter(x => x != "2");
// gives ["1", "3"]
Something close to your code (the converting functions are pretty crappy, don't use them as they are, I just want to provide some context for the previous code):
var itos = i => `${i}`; // integer to string
var stoa = s => s.split(""); // string to array
var atos = a => a.join(""); // array to string
var isIn = (x, set) => set.indexOf(x) != -1;
var unusedDigits = function (i) {
// allDigits is ["0", "1", ..., "9"]
var allDigits = stoa("0123456789");
// if i is 12 then usedDigits is ["1", "2"]
var usedDigits = stoa(itos(i));
// convert filtering result to a string
return atos(
// make a set of digits not in usedDigits
allDigits.filter(
// d will be "0" then "1" ... until "9"
d => !isIn(d, usedDigits)
)
);
};
document.write(JSON.stringify(
unusedDigits(13579) // gives "02468"
));