Чтобы найти целочисленные (Fixnum) значения в ruby array

#ruby #fixnum

#ruby #fixnum

Вопрос:

У меня есть массив [1, 2, "3", "4", "1a", "abc", "a"] с

  • чистые целые числа ( 1 , 2 ),
  • целые числа в строковом формате ( "1" , "2" ),
  • строки ( "a" , "b" ) и
  • смешанные номера строк ( "1a" , "2s" ).

Из этого мне нужно выбрать только целые числа (включая формат строки) 1 , 2 , "3" , "4" .,,,,,,,,,,.

Сначала я попробовал с to_i :

 arr = [1, 2, "3", "4", "1a", "abc", "a"]
arr.map {|x| x.to_i}
# => [1, 2, 3, 4, 1, 0, 0]
  

но это преобразуется "1a" в 1 , чего я не ожидаю.

Затем я попытался Integer(item) :

 arr.map {|x| Integer(x) }  # and it turned out to be
# => ArgumentError: invalid value for Integer(): "1a"
  

Теперь у меня закончились варианты прямого преобразования. Наконец, я решил сделать этот способ, который преобразует значение to_i и to_s . So "1" == "1".to_i.to_s является целым числом, но не "1a" == "1a".to_i.to_s и "a" == "a".to_i.to_s

 arr  = arr.map do |x|
  if (x == x.to_i.to_s)
    x.to_i
  else
    x
  end
end
  

и

 ids, names= arr.partition { |item| item.kind_of? Fixnum }
  

Теперь я получил массивы целых чисел и строк. Есть ли простой способ сделать это?

Комментарии:

1. -1. Вы пишете, что ваш массив содержит целые числа в строковом формате «1», «2», но их нет в вашем массиве. Кроме того, строка «b» и смешанные номера строк «2s» не найдены.

2. вам нужно возвращать его как целые числа или как исходный тип. Я имею в виду, вам нужно получить [1,2,3,4] или [1,2,"3","4"] ?

3. @sawa, это опечатка, sawa … я имел в виду ввести «3», «4». какая разница, что говорят числа в строковом формате. это пример, который я хотел передать…

4. Если объяснения и примеры противоречат друг другу, как можно узнать ваше намерение? Если вопрос труден для понимания или не имеет смысла, то это не очень хороший вопрос.

Ответ №1:

Аналогичное решение, предоставленное @maerics, но немного тоньше:

 arr.map {|x| Integer(x) rescue nil }.compact
  

Комментарии:

1. Я хотел опубликовать почти то же самое, но используя select вот так: >> a.select { |i| Integer(i) rescue false } #=> [1, 2, "3", "4"] . В любом случае, поскольку решение настолько похоже, я оставлю вам это. 🙂

2. Я бы сказал, что эта идиома больше питонистская, чем rubyist «Просить прощения, а не разрешения». Однако в Ruby восстановление исключения может быть дорогостоящим с точки зрения производительности, смотрите Этот тест: technicaldebt.com/the-cost-of-using-rubys-rescue-as-logic

Ответ №2:

 class Array
  def to_i
    self.map {|x| begin; Integer(x); rescue; nil; end}.compact
  end
end

arr = [1, 2, "3", "4", "1a", "abc", "a"]
arr.to_i # => [1, 2, 3, 4]
  

Ответ №3:

что-то вроде этого:

 a = [1,2,"3","4","1a","abc","a"]



irb(main):005:0> a.find_all { |e| e.to_s =~ /^d $/ }.map(amp;:to_i)
=> [1, 2, 3, 4]
  

Комментарии:

1. Я бы поместил to_i внутри find_all блока. Это предотвратит двойную итерацию.

Ответ №4:

Привет, спасибо, что пробудил мой ruby. Вот мой подход к этой проблеме:

 arr=[1,2,"3","4","1a","abc","a"]
arr.map {|i| i.to_s}.select {|s| s =~ /^[0-9] $/}.map {|i| i.to_i}
//=> [1, 2, 3, 4]
  

Ответ №5:

Я заметил, что большая часть ответа до сих пор изменяет значение «3» и «4» на фактические целые числа.

 >> array=[1, 2, "3", "4", "1a", "abc", "a", "a13344a" , 10001, 3321]
=> [1, 2, "3", "4", "1a", "abc", "a", "a13344a", 10001, 3321]
>> array.reject{|x| x.to_s[/[^0-9]/] }
=> [1, 2, "3", "4", 10001, 3321]
  

@OP, я не тестировал свое решение исчерпывающе, но пока, похоже, оно работает (конечно, это сделано в соответствии с предоставленным образцом), поэтому, пожалуйста, тщательно протестируйте сами.

Ответ №6:

Как насчет этого?

 [1,2,"3","4","1a","abc","a"].select{|x| x.to_i.to_s == x.to_s}
# => [1, 2, "3", "4"]
  

Ответ №7:

Выглядит довольно просто

 arr.select{ |b| b.to_s =~ /d $/ }
# or
arr.select{ |b| b.to_s[/d $/] }
#=> [1, 2, "3", "4"]