loading...

Codewars - Unique In Order

jam3sn_ profile image James Newman ・2 min read

So I've worked through a few Codewars challenges now, but I want to try methods of better retaining what I learn. So I'm going to give blogging a go! This is my first, so bear with while I settle in.


Challenge Unique In Order
Language PHP
Brief Implement the function unique_in_order which takes as argument a sequence and returns a list of items without any elements with the same value next to each other and preserving the original order of elements.

Example:

uniqueInOrder('AAAABBBCCDAABBB') == ['A', 'B', 'C', 'D', 'A', 'B']
uniqueInOrder('ABBCcAD') == ['A', 'B', 'C', 'c', 'A', 'D']
uniqueInOrder([1,2,2,3,3]) == [1,2,3]

Function outline:

function uniqueInOrder($iterable){
  return $ret;
}

Okay, so first we need to check if the provided parameter $iterable is empty and that it's also a string. If it's a string, we need to split it into an array of characters. Usually I use explode($delimeter, $string) for exploding with a delimiter, but in this case, we don't have a delimiter. So from a quick google, I came across str_split($string) which is perfect.

function uniqueInOrder($iterable){
  // If empty, return an empty array
  if (empty($iterable)) {
      return $ret;
  }

  // If string, split into an array
  if (is_string($iterable)) {
      $iterable = str_split($iterable);
  }
}

Sweet. So next we're going to iterate over $iterable, but first, we're going to create an empty array to add the unique values to. We'll use the pre-coded return variable $ret.

Now let's iterate. For this, I'm just going to use foreach and check if the last value in our $ret matches the iteration value. If not, it's unique in the order, so let's add it to the $ret array. While I used array_push($item) (been doing too much JS recently 😅), $ret[] = $item would have worked too.

function uniqueInOrder($iterable){
  $ret = [];

  if (empty($iterable)) {
      return $ret;
  }


  if (is_string($iterable)) {
      $iterable = str_split($iterable);
  }


  foreach($iterable as $item) {
      if (end($ret) !== $item) {
          array_push($ret, $item);
      }
  }


  return $ret;
}

Tests run and bam, all passed!

Review

The whole purpose of these exercises is to test my knowledge, fill the patches and see other peoples solutions. So let's break down the top answer.

function uniqueInOrder($iterable){
  $arr = is_string($iterable) ? str_split($iterable) : $iterable;
  $ret = array_reduce($arr, function($carry, $item) {
      if ($item != end($carry)) {
          $carry[] = $item;
      }
      return $carry;
  }, []);

  return $ret;
}

Okay, so it's a bunch shorter than mine 😅

They've made use of shorthand to assign the array to iterate over on line 2, not something I would have thought about, but it's a good idea.

Next, instead of using foreach they've gone with array_reduce, I've tried writing an explanation for this function, but have been unsuccessful on making it clear and concise, so here are the docs....

Great, so the $carry is returned and bam, all done!

What have I learnt?

  1. str_split() splits a string's characters into an array.
  2. array_reduce... Not too sure. I need to do some more research into the pros of this over a foreach.

If you have any comments, suggestions or further information then I'd love to hear from you!

Posted on Mar 20 '19 by:

jam3sn_ profile

James Newman

@jam3sn_

Developer from Wales. Coder, tinkerer, and general geek.

Discussion

markdown guide