Random JavaScript Tips
Nick Scialli
November 16, 2019
Introduction
Sometimes I find clever, interesting, or overlooked ways to solve certain problems in JavaScript. This is a first attempt to capture some of those items, randomly, in no particular order. I’m going to attempt to phrase these ideas as stackoverflow-esque questions/answers as we’re often googling the question we are trying to solve in the moment!
How do I keep only the items in one array that are also in another array?
Onemight be tempted to use the Array includes
method for this solution, but that would be pretty inefficient:
const arr1 = [1, 2, 3, 2, 4, 5, 6];
const arr2 = [2, 4, 6];
const filtered = arr1.filter((el) => arr2.includes(el));
The big efficiency problem here is that it’s a loop inside a loop (filter
loops through arr1
and includes
loops through arr2
for each element of arr1
). For a more efficient solution, consider using a Set
to achieve hash table efficiency:
const arr1 = [1, 2, 3, 2, 4, 5, 6];
const arr2 = [2, 4, 6];
const arr2Set = new Set(arr2);
const filtered = arr1.filter((el) => arr2Set.has(el));
Now, you iterate through arr1
once (with filter) and arr2
once (when creating your Set
). Note that, in this case, creating a new Set is only more efficient than using includes
when the arrays get in the ~100 element range. If you’re optimizing for performance, be sure to do performance testing with your anticipated array sizes!
How do I flip keys and values in an object?
I have seen this accomplished using a combination of Object.entries
and Array reduce
, but I think a simple for...in
loop is the most efficient way to accomplish this task
const myObj = {
a: 'aKey',
b: 'bKey',
c: 'cKey',
};
const reversed = {};
for (key in myObj) {
reversed[myObj[key]] = key;
}
How do I generate a random integer in a range, but exclude a subset of integers?
To accomplish this task, let’s create a function that takes the starting integer, ending integer, and an array of integers to exclude. For efficiency, we create an excludeLookup
using a Set
. We then do a for
loop from the min
to max
value, only adding items to a nums
array when they’re not in our excludeLookup
set. Finally, we generate a random number by selecting a random element in our nums
array!
function randomInt(min, max, exclude) {
const nums = [];
const excludeLookup = new Set(exclude);
for (let i = min; i <= max; i++) {
if (!excludeLookup.has(i)) nums.push(i);
}
if (nums.length === 0) return false;
const randomIndex = Math.floor(Math.random() * nums.length);
return nums[randomIndex];
}
console.log(randomInt(1, 5, [2, 3]));
How can I safety access child properties of an object when I don’t know if a parent object exists?
While we’re still waiting for optional chaining to be implemented widely, we can implement a safelyGet
function that will let us either access deep object props or specify a safe fallback.
function safelyGet(obj, path, fallback = undefined) {
let needle = obj;
const found = path.every((el) => {
if (needle[el] === undefined) return false;
needle = needle[el];
return true;
});
return found ? needle : fallback;
}
// Usage
const myObj = {
user: {
bio: {
age: 25,
},
},
};
const age = safelyGet(myObj, ['user', 'bio', 'age']);
console.log(age); // 25
const permissions = safelyGet(myObj, ['user', 'auth', 'permissions'], 'none');
console.log(permissions); // "none"
How do I filter a list of items by an arbitrary starting string?
Perhaps you have a list of cities that you want to filter by a certain search string, but you only want to match the begging of the list of cities. To accomplish this, you can use indexOf
and filter
!
const cities = [
'Barcelona',
'Berlin',
'Bucharest',
'Budapest',
'Dublin',
'Lisbon',
];
const search = 'bu';
const filtered = cities.filter(
(city) => city.toLowerCase().indexOf(search.toLowerCase()) === 0
);
console.log(filtered); // ["Bucharest", "Budapest"];
How can I truly shuffle an array?
The best method I’ve found for shuffling an array is to iterate through each element in the array and chose another element at random from the array to swap with it. This method is detailed on javascript.info here and is shown below. Note that this particular implementation creates a new array rather than modifying the input array.
function shuffle(oldArray) {
const array = [...oldArray];
for (let i = array.length - 1; i > 0; i--) {
let j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
}
Conclusion
Okay, that’s enough for now. Stay tuned for part 2 at some point… maybe!
Nick Scialli is a senior UI engineer at Microsoft.