How to delete from a multidimensional array in Ruby? - ruby

I am adding to an array using:
server.bans << { :mask => "#{user}", :who => "#{server}", :when => Time.now.to_i }
What is the simplest method to reverse this command?
Should I be using .remove? If so what should I pass to it, the same as what I used in the <<?

You can use Array#pop to remove the last element of the array:
server.bans.pop

You can also use Array#delete_if, if you want to remove elements which meet certain criteria:
server.bans.delete_if{ |u| u[:mask] == "#{user}" }

You could get the object_id of each element in the Array to use as a future reference. While using pop will work, it is not available once another element of the Array is added.
To view object_id of elements. Possibly store these in it's own Array.
server.bans do |ban|
puts ban.object_id
end

Ruby array provide delete_if method to delete items from array conditions. You can use this method as
server.bans.delete_if{ |u| u[:mask] == user.to_s }
To get more details of delete_if http://ruby-doc.org/core-2.2.2/Array.html#method-i-delete_if
Further you can also user remove! method

Related

How to sort the strings within an array in Ruby

I'm just trying to sort my strings alphabetically but while maintaining their position inside an array. For example, I have :
myArray = ["tree", "house", "show", "merit", "timer"]
and I'd like to perform an each loop on it in order to output :
myArray = ["eert", "ehosu", "hosw", and so on...]
I wanted to do something like this :
myArray.each do |x|
x.chars.sort.join
end
For a single string that works but I guess "chars" doesn't work for multiple strings in an array. Or maybe it does and I'm not doing it right. Basically how would I modify it in order to get that output?
All you need in order to make this work is to call map on myArray, instead of each.
The map method will change each element to the result of running the block on the original element.
myArray = ["tree", "house", "show", "merit", "timer"]
myArray.map do |x|
x.chars.sort.join
end
# => ["eert", "ehosu", "hosw", "eimrt", "eimrt"]
Another thing to mention is that you are using camelCase for your variables, while the convention in Ruby is snake_case (my_array would be preferable).
You are sorting each element in the array. To do this, call the map function. I then broke down each element into multiple smaller array elements, and sorted that array. I transformed that array back into a sentence by using the join method.
myArray.map{|x|x.chars.sort{|x,y|x<=>y}.join}
=> ["eert", "ehosu", "hosw", "eimrt", "eimrt"]

How to check in Ruby if an array contains other arrays?

I have a multidimensional array like this:
main_array = [ [["a","b","c"],["d","e"]], [["e","f"],["g","h"]] ]
And I would like to check whether main_array contains other arrays.
I've thought that this will work main_array.include?(Array), but i was wrong.
To answer your question directly, I will use #grep method
main_array.grep(Array).empty?
This will ensure that, if your main_array contains at least one element as Array, if returns false.
main_array.grep(Array).size == main_array.size
This will tell you, if all elements are array or not.
You can use the Enumerable#all? if you want to check that the main array contains all arrays.
main_array.all? { |item| item.is_a?(Array) }
or Enumerable#any?
main_array.any? { |item| item.is_a?(Array) }
if you want to check if main_array contains any arrays.
You can use Enumerable#any?:
main_array.any?{|element| element.is_a? Array}
The code you tried (main_array.include?(Array) didn't work because it's checking if the array main_array includes the class Array, e.g. [Array].include?(Array) #=> true).
main_array != main_array.flatten

Ruby - If element in array contains a certain character, return the associated element(s)

Example:
my_array = ['2823BII','4A','76B','10J']
[using magical method delete_if_doesnt_contain()]
my_array.map! do |elements|
elements.delete_if_doesnt_contain('A')
end
I want that to set my_array = ['4A']
Even if I could iterate through an array and just return the index of the element that contains an 'A' I'd be happy. Thanks for any help!
Thanks for the answers below, but one more question.
other_array = ['4']
my_var = other_array.to_s
my_array.select!{|x| x.include?(my_var)}
This isn't working for me. What am I missing? Something happen when I converted the array to a string?
Very easy using #select :
my_array = ['2823BII','4A','76B','10J']
my_array.select { |str| str.include?('A') }
# => ["4A"]
Or if you want to modify the source array, do use the bang version of select :-
my_array.select! { |str| str.include?('A') }
Arup's answer is correct.
However, to answer your last question specifically, "iterate through an array and just return the index of the element that contains an 'A'", the "index" method returns the index for a matching element:
my_array.index {|x| x.include?('A') }
The grep method is a lot shorter
my_array = ['2823BII','4A','76B','10J']
my_array.grep /A/

Is there a Ruby idiom for encapsulating an object in an Array if it isn't already?

I am working with an external API with which I'm exchanging XML messages. So I use a lot of Hash#from_xml.
However, #from_xml only encodes elements in an Array if they are repeating elements. It makes sense, but it breaks when I am trying to loop through a repeatable element that appears only once. For example:
<Stuff>
<SKU>ABC-123</SKU>
<SKU>DEF-456</SKU>
<SKU>XYZ-789</SKU>
</Stuff>
works great, because:
my_hash = Hash.from_xml(xmlstring)["Stuff"]
will contain 3 SKUs, so I can do:
my_hash["Stuff"].each do |sku|
# process the sku
end
But it fails with this XML:
<Stuff>
<SKU>XYZ-789</SKU>
</Stuff>
because myhash['SKU'] is a Hash, not an Array. I'm having to do this now:
my_hash['SKU'] = [my_hash['SKU']] if my_hash['SKU'].kind_of?(Hash)
Is there a cleaner way?
Just wrap it in an array and flatten it:
array_of_one_or_many = [my_hash['SKU']].flatten
If it's already an array it will unwrap it and make it a common array anyway. Works for both cases.
When I've encountered this in the past, I've used
foo = ([] << bar).flatten
bar is the object and foo will be a flat array.
You can use Array()
irb(main):012:0> Array(1)
=> [1]
irb(main):013:0> Array([1])
=> [1]

Ruby: Selecting a set of array indices whose elements pass a test

Ruby has a select method that takes an array and returns a subarray consisting of all the elements that pass the test given in a block:
myarray.select{|e| mytest(e)} #=> subarray of elements passing mytest
I am wondering whether there is a simple method to get not these elements, but their indices. I understand you could do this:
indices = []
myarray.each_with_index{|e,i| indices << i if mytest(e)}
But I'm looking for a one-liner. Does one exist? Please don't write an extension to the Array class, I know you can get a one-liner that way.
Another one-liner:
(0...myarray.length).select {|i| mytest(myarray[i])}
Cheers!
Here's a one-liner for you. It selects indexes of elements whose length is 3.
a = ['foo', 'bar', 't']
a.map.with_index{|el, i| i if el.length == 3}.compact # => [0, 1]
Or another one (suggested by #fl00r):
a.reduce([]){|ar,el| ar << a.index(el) if el.size == 3; ar}
Also,
myarray.select{|e| mytest(e)}.map!{|e| myarray.index(e)}
However, this won't work properly if you have any repeated elements.

Resources