루비 - 아직 배열이 아닌 경우 변수를 배열로 우아하게 변환합니다).
배열이 주어지면 단일 요소 또는 0이 배열을 얻습니다. 후자의 두 요소는 각각 단일 요소 배열과 빈 배열입니다.
나는 루비가 이런 식으로 작동할 것이라고 잘못 생각했습니다.
[1,2,3].to_a #= [1,2,3] # Already an array, so no change
1.to_a #= [1] # Creates an array and adds element
nil.to_a #= [] # Creates empty array
하지만 실제로 얻을 수 있는 것은 다음과 같습니다.
[1,2,3].to_a #= [1,2,3] # Hooray
1.to_a #= NoMethodError # Do not want
nil.to_a #= [] # Hooray
그래서 이것을 해결하기 위해, 저는 다른 방법을 사용해야 하거나, 제가 사용하고자 하는 모든 클래스의 방법을 to_a로 수정하여 프로그램을 만날 수 있습니다. 이것은 저에게 선택사항이 아닙니다.
방법은 다음과 같습니다.
result = nums.class == "Array".constantize ? nums : (nums.class == "NilClass".constantize ? [] : ([]<<nums))
문제는 그것이 약간 엉망이라는 것입니다.이것을 하는 우아한 방법이 있습니까?(만약 이것이 이 문제를 해결하는 루비 같은 방법이라면 저는 놀랄 것입니다.)
이것은 어떤 응용 프로그램이 있습니까?어레이로 변환할 필요가 있습니까?
레일즈의 액티브 레코드에서 전화를 걸어 이렇게 말합니다.user.posts
게시물 배열, 단일 게시물 또는 0을 반환합니다.이 결과에 영향을 미치는 메소드를 작성할 때 메소드가 0, 1 또는 많은 요소를 포함하는 배열을 사용한다고 가정하는 것이 가장 쉽습니다.예제 방법:
current_user.posts.inject(true) {|result, element| result and (element.some_boolean_condition)}
[*foo]
또는Array(foo)
대부분 작동하지만 해시와 같은 경우에는 엉망이 됩니다.
Array([1, 2, 3]) # => [1, 2, 3]
Array(1) # => [1]
Array(nil) # => []
Array({a: 1, b: 2}) # => [[:a, 1], [:b, 2]]
[*[1, 2, 3]] # => [1, 2, 3]
[*1] # => [1]
[*nil] # => []
[*{a: 1, b: 2}] # => [[:a, 1], [:b, 2]]
해시에 대해서도 작동한다고 생각할 수 있는 유일한 방법은 방법을 정의하는 것입니다.
class Object; def ensure_array; [self] end end
class Array; def ensure_array; to_a end end
class NilClass; def ensure_array; to_a end end
[1, 2, 3].ensure_array # => [1, 2, 3]
1.ensure_array # => [1]
nil.ensure_array # => []
{a: 1, b: 2}.ensure_array # => [{a: 1, b: 2}]
액티브 지원(레일) 포함: Array.wrap
Array.wrap([1, 2, 3]) # => [1, 2, 3]
Array.wrap(1) # => [1]
Array.wrap(nil) # => []
Array.wrap({a: 1, b: 2}) # => [{:a=>1, :b=>2}]
레일을 사용하지 않는 경우 레일 소스와 유사한 방법을 정의할 수 있습니다.
class Array
def self.wrap(object)
if object.nil?
[]
elsif object.respond_to?(:to_ary)
object.to_ary || [object]
else
[object]
end
end
end
가장 간단한 해결책은 다음과 같습니다.[foo].flatten(1)
제안된 다른 솔루션과 달리 어레이, 해시 및nil
:
def wrap(foo)
[foo].flatten(1)
end
wrap([1,2,3]) #= [1,2,3]
wrap([[1,2],[3,4]]) #= [[1,2],[3,4]]
wrap(1) #= [1]
wrap(nil) #= [nil]
wrap({key: 'value'}) #= [{key: 'value'}]
Array(whatever)
방법을 강구해야 합니다.
Array([1,2,3]) # [1,2,3]
Array(nil) # []
Array(1337) # [1337]
액티브 지원(레일)
ActiveSupport는 이를 위한 매우 좋은 방법을 제공합니다.레일즈가 탑재되어 있으므로 도전적으로 가장 좋은 방법은 다음과 같습니다.
Array.wrap([1, 2, 3]) #=> [1, 2, 3]
Array.wrap(nil) #=> nil
스플랫(루비 1.9+)
스플랫 연산자(*
) 배열을 해제합니다(가능한 경우).
*[1,2,3] #=> 1, 2, 3 (notice how this DOES not have braces)
물론, 배열이 없으면 이상한 일이 발생하고, "스플릿"하는 개체는 배열에 넣어야 합니다.좀 이상하지만, 의미는 다음과 같습니다.
[*[1,2,3]] #=> [1, 2, 3]
[*5] #=> [5]
[*nil] #=> []
[*{meh: "meh"}] #=> [[:meh, "meh"], [:meh2, "lol"]]
ActiveSupport가 없는 경우 다음 방법을 정의할 수 있습니다.
class Array
def self.wrap(object)
[*object]
end
end
Array.wrap([1, 2, 3]) #=> [1, 2, 3]
Array.wrap(nil) #=> nil
그러나 어레이 수가 크고 어레이 수가 적은 경우에는 변경해야 할 수도 있습니다. 위의 방법은 대규모 어레이에서는 속도가 느리고 스택 오버플로(omg so meta)가 발생할 수도 있습니다.어쨌든 이 작업을 대신 수행할 수 있습니다.
class Array
def self.wrap(object)
object.is_a? Array ? object : [*object]
end
end
Array.wrap([1, 2, 3]) #=> [1, 2, 3]
Array.wrap(nil) #=> [nil]
저는 또한 테너레이 운영자가 있거나 없는 벤치마크를 가지고 있습니다.
어때.
[].push(anything).flatten
이것이 지구와 주변 지역에서 볼 수 있는 가장 맛있는 통사 설탕이 아니라는 것을 아는 위험을 무릅쓰고, 이 코드는 당신이 설명하는 것과 정확히 같습니다.
foo = foo.is_a?(Array) ? foo : foo.nil? ? [] : [foo]
개체의 배열 방법을 덮어쓸 수 있습니다.
class Object
def to_a
[self]
end
end
모든 것은 Object를 상속하므로 이제 to_a는 태양 아래의 모든 것에 대해 정의될 것입니다.
나는 모든 답을 검토했고 대부분 루비 2+에서 일하지 않습니다.
하지만 엘라도는 가장 우아한 해결책을 가지고 있습니다.
액티브 지원(레일) 포함:Array.wrap
Array.wrap([1, 2, 3]) # => [1, 2, 3]
Array.wrap(1) # => [1]
Array.wrap(nil) # => []
Array.wrap({a:1, b:2}) # => [{a=>1, :b=>2}]
슬프게도 이것은 또한 루비 2+에 대해서도 작동하지 않습니다. 왜냐하면 당신은 오류를 얻을 것이기 때문입니다.
undefined method `wrap' for Array:Class
이 문제를 해결하기 위해서는 필요합니다.
'active_support/decretion'이(가) 필요합니다.
'active_support/core_ext/array/message'가 필요합니다.
메소드 이후로#to_a
가지 가 있는클래스에 합니다.Nil
그리고.Hash
), 을 통해 하면 됩니다.Object
:
class Object
def to_a
[self]
end
end
그런 다음 모든 개체에 대해 해당 메소드를 쉽게 호출할 수 있습니다.
"Hello world".to_a
# => ["Hello world"]
123.to_a
# => [123]
{a:1, b:2}.to_a
# => [[:a, 1], [:b, 2]]
nil.to_a
# => []
언급URL : https://stackoverflow.com/questions/18358717/ruby-elegantly-convert-variable-to-an-array-if-not-an-array-already
'programing' 카테고리의 다른 글
jQuery를 사용하여 다단계 양식 재설정 (0) | 2023.06.01 |
---|---|
VBA 내에서 Excel에서 시트의 데이터를 새로 고치는 중 (0) | 2023.06.01 |
아이폰처럼 HTML 텍스트 입력 상자에 클리어 버튼을 넣으려면 어떻게 해야 합니까? (0) | 2023.06.01 |
루비 블록에서 탈출하는 방법은? (0) | 2023.06.01 |
JVM 대상 1.8로 빌드된 바이트 코드를 JVM 대상 1.6으로 빌드되는 바이트 코드로 인라인할 수 없습니다. (0) | 2023.06.01 |