Categories
JavaScript Answers Lodash

How to get duplicate values from an array with Lodash?

Sometimes, we want to get duplicate values from an array with Lodash.

In this article, we’ll look at how to get duplicate values from an array with Lodash.

How to get duplicate values from an array with Lodash?

To get duplicate values from an array with Lodash, we can use the filter and includes methods.

For instance, we write:

const arr = [1, 2, 2, 3, 3]
const dups = _.filter(arr, (val, i, iteratee) => _.includes(iteratee, val, i + 1));

console.log(dups)

We have an arr array that has some duplicate values.

Then we call filter with arr and a callback that calls includes to check if the array has the duplicate entries of val.

Therefore, dups is [2, 3].

Conclusion

To get duplicate values from an array with Lodash, we can use the filter and includes methods.

Categories
Lodash

Learning JavaScript by Implementing Lodash Methods — Playing With Function Arguments

Lodash is a very useful utility library that lets us work with objects and arrays easily.

However, now that the JavaScript standard library is catching up to libraries such as Lodash, we can implement many of the functions in simple ways.

In this article, we’ll look at how to implement more Lodash methods that are used to manipulate function arguments.

flip

The Lodashy flip method applies the arguments to a function in reverse order.

We can easily implement this ourselves with the spread operator. For instance, we can create our own flip method as follows:

const flip = (fn) => (...args) => fn(...args.reverse())

In the code above, we created the flip function by getting the fn parameter, which is a function.

Then we return a function with the args array and then return fn with the args applied in reverse by calling args.reverse() and then use the spread operator to apply the arguments.

We can then call it as follows:

const flipped = flip((...args) => args);

And then when we call the flipped function as follows:

flipped('a', 'b', 'c', 'd')

We then see that the returned value is [“d”, “c”, “b”, “a”] .

negate

The Lodash negate method that returns a function that negates the predicate that’s passed into the negate method.

For instance, we can write the following code:

const negate = (predicate) => (...args) => !predicate(...args)

In the code above, we created the negate function by making a function that takes in a predicate and then return a function that takes in the args and then return the predicate called with args spread by the spread operator negated.

Then we can call it as follows:

const isEven = (n) => n % 2 == 0;
[1, 2, 3, 4, 5, 6].filter(negate(isEven))

We called by first defining an isEven function that has the condition that the n % 2 == 0 , which returns true if the number is even.

Then we can used it with the filter method as follows:

[1, 2, 3, 4, 5, 6].filter(negate(isEven))

We negated the isEven method’s returned value with negate , so the returned numbers are odd numbers.

partial

The Lodash partial method returns a function that takes a function with the arguments partially applied to it. Then we can call that returned function with more arguments.

For instance, we can create our own partial method with the following code:

const partial = (fn, ...partialArgs) => (...args) => fn(...partialArgs, ...args)

In the code above, we created a function that takes fn , which is a function, and partialArgs , which are some of the arguments that are called. Then we return a function that takes more arguments and calls fn with the partialArgs and args spread within the fn .

Both partialArgs and args are applied to fn with the spread operator.

Then we can call it as follows:

const greet = (greeting, name) => {
  return `${greeting} ${name}`;
}

const sayHelloTo = partial(greet, 'hello');
console.log(sayHelloTo('joe'));

We defined the greet function, which takes 2 arguments. With our partial function, we returned a function with the first greeting argument and then returns the function with the given argument applied and set it to sayHelloTo

Then we call sayHelloTo and with the 2nd argument and then we can see from the console log that it’s hello joe as we expected.

partialRight

The partialRight method is like partial , except that we apply the arguments from right to left instead.

We can just change partial slightly to create the partialRight function as follows:

const partialRight = (fn, ...partialArgs) => (...args) => fn(...args, ...partialArgs)

In the code above, we just flipped the partialArgs and args order.

Then we can call it as follows:

function greet(greeting, name) {
  return `${greeting} ${name}`;
}

const greetFred = partialRight(greet, 'joe');
console.log(greetFred('hi'));

We defined the greet function with the greeting and name arguments and then we applied the arguments in reverse order.

Then we get that console log outputs 'hi joe' .

Conclusion

The flip method returns a function that has the arguments applied in reverse. We can implement that easily with the spread and rest operators.

Lodash’s negate method returns a function that negates the result of the given predicate function. We can just return a function that negates the returned result of the predicate function.

The partial and partialRight methods return a function that’s partially applied partially and takes more arguments that’s applied in addition to the partially applied arguments.

Categories
Lodash

Learning JavaScript by Implementing Lodash Methods — Combining Values

Lodash is a very useful utility library that lets us work with objects and arrays easily.

However, now that the JavaScript standard library is catching up to libraries such as Lodash, we can implement many of the functions in simple ways.

In this article, we’ll look at how to implement Lodash methods that deal with combining items in a collection.

reduce

The Lodash reduce method combines the values in a collection into one value by calling the iteratee function, which takes an accumulator parameter with the values that are combined so far and the 2nd parameter is the item to be combined for the array version.

The object version takes the result , which has the accumulated value, value , which has the value of the object, and key which has the key of the object that’s being processed.

It also takes an optional accumulator object with the initial value of the accumulator parameter before iteratee is run.

Then we can write the following code:

const reduce = (collection, iteratee, accumulator) => {
  if (Array.isArray(collection)) {
    return collection.reduce(iteratee, accumulator)
  } else {
    let reduced = accumulator;
    for (const key of Object.keys(collection)) {
      iteratee(reduced, collection[key], key)
    }
    return reduced;
  }
}

In the code above, we check if collection is an array. If it is, then we call reduce on the array instance with the iteratee function as the callback and the accumulator as the initial value.

Otherwise, we create a new reduced variable with the accumulator as the initial value.

Then we loop through the keys of the collection object with the iteratee , which takes the reduced value, the value of the given key and the key itself as the arguments.

We then return the reduced object, which has the combined results.

Then we can call it as follows:

const result = reduce({
  'a': 1,
  'b': 2,
  'c': 1
}, (result, value, key) => {
  (result[value] || (result[value] = [])).push(key);
  return result;
}, {});

In the code above, we called our own reduce method with an object and a iteratee function with the result , value , and key parameters. Then in the function, we combined the values by populating the keys of the resulting object with the value and push the keys into the array.

Then we get:

{
  "1": [
    "a",
    "c"
  ],
  "2": [
    "b"
  ]
}

as the value of result .

We can also call our reduce function with an array as follows:

const result = reduce([1, 2], (sum, n) => {
  return sum + n;
}, 0);

Then we get that result is 3.

Photo by Brett Jordan on Unsplash

reduceRight

The reduceRight method is similar to reduce except that the values are combined from the end to the start.

We can implement it in a similar way to reduce as follows:

const reduceRight = (collection, iteratee, accumulator) => {
  if (Array.isArray(collection)) {
    return collection.reverse().reduce(iteratee, accumulator)
  } else {
    let reduced = accumulator;
    const keys = Object.keys(collection)
    for (let i = keys.length - 1; i >= 0; i--) {
      iteratee(reduced, collection[keys[i]], keys[i])
    }
    return reduced;
  }
}

In the code above, in the array case, we reversed the array by calling reduce with the same arguments as the reduce implementation.

Otherwise, we loop through the object’s keys in reverse order. In the loop, we call iteratee on each item. The iteraee function takes the same parameters as the one we pass into reduce .

We can call reduceRight as follows:

const result = reduceRight({
  'a': 1,
  'b': 2,
  'c': 1
}, (result, value, key) => {
  (result[value] || (result[value] = [])).push(key);
  return result;
}, {});

Then we get that result is:

{
  "1": [
    "c",
    "a"
  ],
  "2": [
    "b"
  ]
}

since we looped through object entries in reverse order.

We can call reduceRight with an array as follows:

const result = reduceRight([1, 2], (sum, n) => {
  return sum + n;
}, 0);

Then we get the same result as reduce , which is 3.

Conclusion

The reduce and reducerRight methods can be done with existing array methods for arrays. We can just call reduce on the array instance with the iteratee function and the accumulator .

For objects, it’s more complex. We have to loop through the items by getting the keys and the pass the keys and values into the iteratee function, which takes the result as the first argument. The second argument is the value and the 3rd is the key .

Categories
Lodash

Learning JavaScript by Implementing Lodash Methods — Grouping Items

Lodash is a very useful utility library that lets us work with objects and arrays easily.

However, now that the JavaScript standard library is catching up to libraries such as Lodash, we can implement many of the functions in simple ways.

In this article, we’ll look at how to implement Lodash methods that deal with grouping items in a collection.

keyBy

They keyBy method groups collection entries into keys as returned by a function that takes an entry as the parameter and returns the key according to what’s in the function’s code.

We can create our own keyBy function as follows:

const keyBy = (arr, fn) => {
  let obj = {};
  for (const a of arr) {
    obj[fn(a)] = a;
  }
  return obj;
}

In the code above, we just created an empty object, then populated it by calling fn with the array entry from the for...of loop and use it as the key.

Then the corresponding array entry is set as the value, and the object is returned.

When we call it as follows:

const arr = [{
    'dir': 'left',
    'code': 99
  },
  {
    'dir': 'right',
    'code': 100
  }
];
const result = keyBy(arr, o => String.fromCharCode(o.code))

Then result is:

{
  "c": {
    "dir": "left",
    "code": 99
  },
  "d": {
    "dir": "right",
    "code": 100
  }
}{
  "c": {
    "dir": "left",
    "code": 99
  },
  "d": {
    "dir": "right",
    "code": 100
  }
}

map

The map method returns an array that is mapped from the original array by calling a function on each entry and putting it in the new array.

Since the plain JavaScript has a map method for array instances, we can just use it to implement the Lodash map method.

Lodash’s map method also takes an object as an argument, which takes the keys and then maps the values with a function and put the values in the returned array.

We can implement this as follows:

const map = (collection, iteratee) => {
  if (Array.isArray(collection)){
    return collection.map(iteratee);
  }
  else {
    return Object.values(collection).map(iteratee)
  }
}

In the code above, we use the Array.isArray method to check if collection is an array. If it is, then we just use the array’s map method and use iteratee as the callback.

Otherwise, we use Object.values to return an array of object values and call map with iteratee as the callback on it.

Then we can call it as follows:

const result = map([4, 8], x => x**2);

which sets result to:

[
  16,
  64
]

Also, when we run:

const result = map({ 'a': 4, 'b': 8 }, x => x**2);

We get the same result.

partition

The partition method returns an array that’s grouped by the key returned by the function that’s passed in.

It groups an array by the key that’s returned by the function.

We can implement it as follows:

const partition = (collection, predicate) => {
  let obj = {};
  for (const a of collection) {
    if (!Array.isArray(obj[predicate(a)])) {
      obj[predicate(a)] = [];
    }
    obj[predicate(a)].push(a);
  }
  return Object.keys(obj).map(k => obj[k])
}

In the code above, we created an obj object, and then we loop through the collection with a for...of loop.

Then we create an array on with the key of obj that’s created by calling predicate on an entry.

If it’s not an array, then we set it to an empty array. Then we push the items according to the keys.

Finally, we return the values in an array by mapping the keys to the corresponding values.

Then when we call it as follows:

const users = [{
    'user': 'foo',
    'active': false
  },
  {
    'user': 'bar',
    'active': true
  },
  {
    'user': 'baz',
    'active': false
  }
];

const result = partition(users, o => o.active);

We get that result is:

[
  [
    {
      "user": "foo",
      "active": false
    },
    {
      "user": "baz",
      "active": false
    }
  ],
  [
    {
      "user": "bar",
      "active": true
    }
  ]
]

Conclusion

The keyBy method can be implemented by grouping the collections into an object with the for...of loop and populating the keys by calling the iteratee function. Then the values are populated by the corresponding key.

The map method can be implemented by the array instance’s map method.

partition can also be implemented by looping through all the objects and then populating the keys by calling the predicate with the array entry, and then we push the items into the array with the corresponding key.

Categories
Lodash

Learning JavaScript by Implementing Lodash Methods — Functions

Lodash is a very useful utility library that lets us work with objects and arrays easily.

However, now that the JavaScript standard library is catching up to libraries such as Lodash, we can implement many of the functions in simple ways.

In this article, we’ll look at how to implement some Lodash methods for converting functions to different forms.

bind

The Lodash bind function returns a function with a value of this that we set and with some arguments partially applied.

We can implement this by returning a function that calls the passed-in function’s bind method and return it with the arguments partially applied.

For instance, we can write the following code:

const bind = (fn, thisArg, ...partials)=> {
  return (...args) => fn.apply(thisArg, [...partials, ...args])
}

In the code above, we take the fn function, thisArg for the value of this , and partials , which is an array of arguments to be called with fn .

Then we used JavaScript’s function’s apply method to call fn with thisArg as the 1st argument to set the value of this in fn and an array of arguments, which we spread with the spread operator.

We first spread partials to apply them first, then we spread the args which we take in in the returned function.

Then when we call it as follows:

function greet(greeting, punctuation) {
  return `${greeting} ${this.user}${punctuation}`;
}

const object = {
  'user': 'joe'
};
const bound = bind(greet, object, 'hi');
console.log(bound('!'))

We see that the console log should log ‘hi joe!’ since we set the value of this in greet to object . We then applied the partial argument of 'hi' first then we called bound with the exclamation mark.

bindKey

bindKey is similar to bind except that we can use it to apply the same operations as bind to an object’s method.

It also doesn’t let us change the value of this and keep that value as the original object that the method is in.

We can implement bindKey as follows:

const bindKey = (object, key, ...partials) => {
  return (...args) => object[key].apply(object, [...partials, ...args])
}

In the code above, we take object , key , and partials as arguments. Where object is the object with the method we want to call bindKey on.

The key is the key to the method that we want to do the partial argument application on, and partials have the arguments to apply.

We can then run it as follows:

const object = {
  user: 'joe',
  greet(greeting, punctuation) {
    return `${greeting} ${this.user} ${punctuation}`;
  }
};
const bound1 = bindKey(object, 'greet', 'hi');
console.log(bound1('!'))

object.greet = function(greeting, punctuation) {
  return `${greeting} ya ${this.user} ${punctuation}`;
};

const bound2 = bindKey(object, 'greet', 'hi');
console.log(bound2('!'))

In the code above, we have our object with the greet method, which returns a string that reference this.user , which should be 'joe' .

Then we call our bindKey function with the object and the arguments we want to call the returned function with, which will be set to bound1 .

At this stage, bound1 has 'hi' set as the value of greeting . Then when we callbound1 , we passed in the '!' to it, which calls the bound1 with punctuation .

Then we get 'hi joe !’ from the console log.

After that, we changed object.greet to a different function. Now when we call bindKey as we did on the 2nd last line, we get the bound2 function, which has the 'hi' string applied to the object.greet method as the value off greeting .

Then when we call bound2 , we applied the '!' as the value of punctuation . Therefore, we get the string 'hi ya joe !’ logged in the console log output.

delay

The Lodash delay method runs a function after a given wait time in milliseconds. It also takes optional arguments that we can call our function with.

We can implement our own function with the setTimeout function as follows:

const delay = (fn, wait, ...args) => {
  setTimeout((...args) => fn(...args), wait, ...args)
}

In the code above, we just called setTimeout with a callback which calls fn as the first argument. The second argument has the wait time and the args are the arguments that’ll be passed into the callback, which is all the subsequent arguments.

The callback takes the args and then apply them the passed-in function fn .

Then when we call it as follows:

delay((text) => {
  console.log(text);
}, 1000, 'foo');

We get that 'foo' is logged by the function we passed into delay after 1 second.

Conclusion

To implement the bind and bindKey Lodash methods, we can use the JavaScript function’s apply method to change the value of this and apply the arguments to the passed-in function.

We can create our own Lodash delay method with the setTimeout function, which takes the number of milliseconds to delay the function call and the arguments to call the callback with.