0

Good evening. I have a nested name array. Calling specific indices and using == returns true. After using .flatten , using == on the same values returns false.

name_array
=> [["Theo", "Peter Jr.", "Lucky"], ["Theo", "Peter Jr.", "Ms. K"], ["Queenie", "Andrew", "Ms. K", "Alex"], ["Queenie", "Alex"]]
irb(main):044:0> name_array[0][0]
=> "Theo"
irb(main):045:0> name_array[1][0]
=> "Theo"
irb(main):046:0> name_array[0][0] == name_array[1][0]
=> true
irb(main):047:0> name_array.flatten
=> ["Theo", "Peter Jr.", "Lucky", "Theo", "Peter Jr.", "Ms. K", "Queenie", "Andrew", "Ms. K", "Alex", "Queenie", "Alex"]
irb(main):048:0> name_array[0] == name_array[3]
=> false

The end goal here is to return an array of unique names. My first instinct was to use .uniq but that ends up returning the original nested array. It should be noted I first got this nested array by converting a nested hash to an array then adding the array values to name_array.

irb(main):051:0> name_array.flatten
=> ["Theo", "Peter Jr.", "Lucky", "Theo", "Peter Jr.", "Ms. K", "Queenie", "Andrew", "Ms. K", "Alex", "Queenie", "Alex"]
irb(main):052:0> name_array.uniq
=> [["Theo", "Peter Jr.", "Lucky"], ["Theo", "Peter Jr.", "Ms. K"], ["Queenie", "Andrew", "Ms. K", "Alex"], ["Queenie", "Alex"]]
ILikeClouds
  • 35
  • 1
  • 1
  • 4
  • What is your expected output? Because IMO all arrays are different therefore all arrays should be returned. I am wrong? Do you expect a different result? – spickermann Oct 15 '20 at 06:34
  • Ruby always returns the value of the last-executed function, and this is what `irb` prints. When you do `name_array.flatten` it returns a new flattened array, `irb` prints the result. The flattened array isn't assigned to any variable and gets discarded as soon as it goes out of scope. `name_array` still holds the original value. Use `name_array.flatten.uniq` to get the result you want. But you still need to assign the result to a variable... – nullTerminator Oct 15 '20 at 06:46

1 Answers1

2

The main problem here is that #flatten returns a new array and not change the original one.

to solve it you have 2 ways:

  1. Define a new variable with an array that returns after the call of #flatten
flatten_array = name_array.flatten

flatten_array[0] == flatten_array[3]
=> true
  1. Use #flatten!, that change original array:
name_array.flatte!

name_array[0] == name_array[3]

the same with #uniq, to change original use: #uniq!

Summary: to solve what you need:

name_array.flatten!
name_array.uniq # or .uniq!

# OR

flatten_array = name_array.flatten
flatten_array.uniq # or .uniq!

and one more trick, using: #inject and #|

name_array.inject(&:|) # will do the same as name_array.flatten.uniq

P.S. it's second your question with the very same problem, I think this might help you to understand how it works ":) In general: methods with an exclamation mark(!) will change your original variable value, methods without an exclamation mark(!) will return you a new value

Oleksandr Holubenko
  • 4,310
  • 2
  • 14
  • 28