#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"]