Studying at CodeWar (ruby) ③ squeeze, gsub

About this article

Little by little output of what I learned through the recently started Codewar

problem

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.

Sequence as an argument using the function unique_in_order? Is received, and the same value is not adjacent, and the list is returned in the order of the elements.

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

The way I thought

(1) I tried to erase the value used repeatedly, and after converting the received argument into an array, I tried to make it ʻuniq`, but it failed because it became as follows.


def unique_in_order(iterable)
  iterable.chars.uniq
end

unique_in_order('AAAABBBCCDAABBB')
=>["A", "B", "C", "D"]

(2) When I searched for consecutive values, I found the squeeze method. https://docs.ruby-lang.org/ja/latest/method/String/i/squeeze.html

squeeze(*chars) -> String[permalink][rdoc][edit] If multiple characters contained in chars are lined up, combine them into one character.

def unique_in_order(iterable)
  iterable.squeeze.chars
end

unique_in_order('AAAABBBCCDAABBB')
=>["A", "B", "C", "D", "A", "B"]

It's done! !! !! !!

But it's not over yet

When I submitted it, I was angry at three things as follows ❤️

① <NoMethodError: undefined method `squeeze' for []:Array>
② <NoMethodError: undefined method `squeeze' for [1, 2, 3, 3]:Array>
③ <NoMethodError: undefined method `squeeze' for ["a", "b", "b"]:Array>

What they all have in common is that you can't use suqueeze on arrays.

In other words

Shouldn't we just do ʻiterable.squeeze.chars if the argument is a string and ʻiterable.uniq if it's an array?

I succeeded! !! !!

def unique_in_order(iterable)
  if iterable.class == String
    iterable.squeeze.chars
  else
    iterable.uniq
  end
end

Ideal answer

def unique_in_order(iterable)
  case iterable
    when String
      iterable.gsub(/(.)\1*/, '\1').split('')
    when Array
      iterable.uniq
  end
end

Oh wait a minute. I don't understand (laughs)

gsub method

gsub(pattern, replace) -> String Generates and returns a string in which all parts of the string that match pattern are replaced with string replace.

#If you don't use regular expressions
#String.gsub(置換したいString, 置換後のString)

#When using regular expressions
#String.gsub(/Regular expressions/, Regular expressionsに該当した箇所を置換した後のString)

p 'abcdefg'.gsub(/def/, '!!')          # => "abc!!g"
p 'abcabc'.gsub(/b/, '<<\&>>')         # => "a<<b>>ca<<b>>c"
p 'xxbbxbb'.gsub(/x+(b+)/, 'X<<\1>>')  # => "X<<bb>>X<<bb>>"
p '2.5'.gsub('.', ',') # => "2,5"

Are you doing it using regular expressions? I'll do a little more research on this before updating!

Recommended Posts

Studying at CodeWar (ruby) ③ squeeze, gsub
Studying at CodeWar (ruby) ②
Studying at CodeWar (ruby) ⑥ inject
Studying at CodeWar
Studying with CodeWar (ruby) ⑤ proc
Studying with CodeWar (ruby) ④ case ~ when
Start studying Ruby