루비-배열이 아닌 경우 변수를 배열로 우아하게 변환
배열, 단일 요소 또는 nil이 주어지면 배열을 얻습니다. 후자는 두 요소가 단일 요소 배열이고 빈 배열입니다.
나는 루비가 이런 식으로 수리 잘못 생각했다.
[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
방법을 사용하는 경우 사용하려는 모든 클래스의 사용 방법을 수정하여 메타 프로그램을 사용할 수 있습니다.
따라서 방법은 다음과 가변적입니다.
result = nums.class == "Array".constantize ? nums : (nums.class == "NilClass".constantize ? [] : ([]<<nums))
문제는 약간의 혼란스러워한다는 것입니다. 제출하는 우아한 방법이 있습니까? (이 문제를 루비 같은 방법이라면 놀랍습니다)
어떤 응용 프로그램이 있습니까? 왜 배열로 변환?
say라고 부르는 Rails의 ActiveRecord에서 user.posts
게시물의 배열, 단일 게시물 또는 nil을 반환합니다. 이 결과에서 작동하는 메소드를 사용할 때 메소드가 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}]
ActiveSupport 사용 (레일) : 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}]
Rails를 사용하지 않는 경우 rails source 와 사용할 수있는 고유 한 방법을 정의 할 수 있습니다 .
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에는 이에 대한 꽤 좋은 방법이 있습니다. Rails가 포함되어 있으므로이를 수행하는 가장 좋은 방법은 다음과 같습니다.
Array.wrap([1, 2, 3]) #=> [1, 2, 3]
Array.wrap(nil) #=> nil
Splat (Ruby 1.9 이상)
표시 연산자 ( *
)는 다음을 수행 할 수있는 경우 배열의 배열을 해제합니다.
*[1,2,3] #=> 1, 2, 3 (notice how this DOES not have braces)
물론, 배열이 없으면 이상한 일을하므로 "splat"객체를 배열에 넣어야합니다. 다소 이상하지만 다음을 의미합니다.
[*[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]
Object의 배열 메소드를 덮어 쓸 수 있습니다.
class Object
def to_a
[self]
end
end
모든 것이 Object를 상속하므로 이제 to_a는 태양 아래의 모든 것에 대해 정의됩니다.
모든 답변을 검토했으며 대부분 루비 2+에서는 작동하지 않습니다.
그러나 elado에는 가장 우아한 솔루션이 있습니다.
ActiveSupport (레일) 사용 : 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 / deprecation'필요
'active_support / core_ext / array / wrap'필요
#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
# => []
'IT' 카테고리의 다른 글
WPF 수준을 이산 정수 위치에만 맞추는 방법은 무엇입니까? (0) | 2020.07.30 |
---|---|
LINQ 문이 'foreach'루프보다 빠릅니까? (0) | 2020.07.30 |
Mac OS X에 내장 vim 업데이트 (0) | 2020.07.30 |
Eclipse에서 CSS 사전 처리를 통합하는 방법은 무엇입니까? (0) | 2020.07.30 |
주요에서 목록이 항목을 공유하는지 테스트 (0) | 2020.07.30 |