programing

루비에서 배열을 반복하는 "올바른" 방법은 무엇입니까?

oldcodes 2023. 7. 13. 21:06
반응형

루비에서 배열을 반복하는 "올바른" 방법은 무엇입니까?

PHP는 모든 사르트르에도 불구하고 이 카운트에서 꽤 좋습니다.배열과 해시 사이에는 차이가 없습니다(아마도 제가 순진할 수도 있지만, 제게는 이것이 분명히 맞는 것 같습니다). 그리고 당신은 그냥 반복합니다.

foreach (array/hash as $key => $value)

루비에는 이런 종류의 일을 할 수 있는 여러 가지 방법이 있습니다.

array.length.times do |i|
end

array.each

array.each_index

for i in array

해시가 더 말이 됩니다. 항상 사용하기 때문입니다.

hash.each do |key, value|

어레이에 대해 이 작업을 수행할 수 없는 이유는 무엇입니까?한 가지 방법만 기억하고 싶다면, 제 생각에 저는 사용할 수 있을 것 같습니다.each_index 사용할 수 있게 에) 해야 .array[index]단순한 의대에 value.


요. 깜빡했어요.array.each_with_index하지만, 이것은 최악입니다. 왜냐하면 그것은 가기 때문입니다.|value, key|그리고.hash.each ㅠㅠ|key, value|미친 거 아니에요?

이렇게 하면 모든 요소가 반복됩니다.

array = [1, 2, 3, 4, 5, 6]
array.each { |x| puts x }

# Output:

1
2
3
4
5
6

값과 인덱스를 제공하는 모든 요소를 반복합니다.

array = ["A", "B", "C"]
array.each_with_index {|val, index| puts "#{val} => #{index}" }

# Output:

A => 0
B => 1
C => 2

당신의 질문으로 볼 때 어떤 것을 찾고 있는지 잘 모르겠습니다.

올바른 방법은 없다고 생각합니다.반복하는 방법은 매우 다양하며, 각각의 틈새시장이 있습니다.

  • each인덱스는 신경 쓰지 않기 때문에 여러 용도로 사용하기에 충분합니다.
  • each_ with _index각각 해시 #처럼 작동합니다. 값과 인덱스를 얻을 수 있습니다.
  • each_index인덱스만 있습니다.저는 이것을 자주 사용하지 않습니다."length.times"는 "length.times"입니다.
  • map한 어레이를 다른 어레이로 변환할 때 유용한 반복 방법입니다.
  • select부분 집합을 선택할 때 사용할 반복기입니다.
  • inject합계 또는 제품을 생성하거나 단일 결과를 수집하는 데 유용합니다.

기억해야 할 것이 많아 보일 수도 있지만, 걱정하지 마세요, 여러분은 그들 모두를 알지 못한 채 살아갈 수 있습니다.하지만 여러분이 다른 방법들을 배우고 사용하기 시작하면, 여러분의 코드는 더 깨끗하고 명확해질 것이고, 여러분은 루비 마스터로 가는 길을 가게 될 것입니다.

그 을 하지 않습니다.Array->|value,index|그리고.Hash->|key,value|미친 것은 아니지만(호레이스 롭의 논평 참조), 저는 이 합의를 기대할 수 있는 건전한 방법이 있다고 말하고 있습니다.

어레이를 다룰 때는 (인덱스가 일시적이기 때문에 인덱스가 아니라) 어레이의 요소에 집중합니다.메소드는 각각 인덱스(즉, 각+인덱스) 또는 |각,인덱스| 또는|value,index|이는 또한 인덱스가 선택적 인수로 표시되는 것과도 일치합니다. |value, index=value|value |value, index|에 해당합니다.

해시를 다룰 때, 저는 종종 값보다 키에 더 집중하고, 보통 키와 값을 그 순서대로 다루고 있습니다.key => value또는hash[key] = value.

오리털 입력을 원하는 경우 Brent Longborough가 표시한 대로 정의된 방법을 명시적으로 사용하거나 Maxhawkins가 표시한 대로 암시적인 방법을 사용합니다.

루비는 언어를 수용하는 것이지 언어를 수용하는 것이 아닙니다.이것이 많은 방법들이 있는 이유입니다.무언가에 대해 생각할 수 있는 방법은 매우 많습니다.루비에서 당신은 가장 가까운 것을 선택하고 나머지 코드는 보통 매우 깔끔하고 간결하게 빠집니다.

"Ruby에서 배열을 통해 반복하는 "올바른" 방법은 무엇입니까?"라는 원래 질문에 대해서는, 핵심 방법(즉, 강력한 통사적 설탕이나 객체 지향적 힘 없이)은 다음을 수행하는 것이라고 생각합니다.

for index in 0 ... array.size
  puts "array[#{index}] = #{array[index].inspect}"
end

하지만 루비는 강력한 통사적 설탕과 물체 지향적인 힘에 관한 것이지만 어쨌든 해시에 대한 동등한 것이며 키는 주문할 수 있거나 주문할 수 없습니다.

for key in hash.keys.sort
  puts "hash[#{key.inspect}] = #{hash[key].inspect}"
end

그래서 제 대답은 "Ruby의 배열을 통해 반복하는 "올바른" 방법은 사용자(즉, 프로그래머 또는 프로그래밍 팀)와 프로젝트에 달려 있습니다."입니다.우수한 Ruby 프로그래머가 더 나은 선택을 할 수 있습니다(어떤 구문 능력 및/또는 어떤 객체 지향 접근법 중).더 나은 루비 프로그래머는 계속해서 더 많은 방법을 찾습니다.


이제 다른 질문을 하겠습니다. "Ruby의 범위를 거꾸로 반복하는 "올바른" 방법은 무엇입니까?"! (이 질문은 제가 어떻게 이 페이지에 오게 되었는지입니다.)

다음을 수행하는 것이 좋습니다(포워드의 경우).

(1..10).each{|i| puts "i=#{i}" }

하지만 저는 (뒤로) 하는 것을 좋아하지 않습니다.

(1..10).to_a.reverse.each{|i| puts "i=#{i}" }

글쎄요, 저는 사실 그렇게 하는 것을 별로 개의치 않지만, 거꾸로 가르칠 때, 저는 제 학생들에게 멋진 대칭성을 보여주고 싶습니다. (예를 들어, 역방향이나 -1 단계만 추가하고, 다른 것은 수정하지 않고)대칭을 위해 다음 작업을 수행할 수 있습니다.

(a=*1..10).each{|i| puts "i=#{i}" }

그리고.

(a=*1..10).reverse.each{|i| puts "i=#{i}" }

내가 별로 좋아하지 않지만, 당신은 할 수 없습니다.

(*1..10).each{|i| puts "i=#{i}" }
(*1..10).reverse.each{|i| puts "i=#{i}" }
#
(1..10).step(1){|i| puts "i=#{i}" }
(1..10).step(-1){|i| puts "i=#{i}" }
#
(1..10).each{|i| puts "i=#{i}" }
(10..1).each{|i| puts "i=#{i}" }   # I don't want this though.  It's dangerous

당신은 궁극적으로 할 수 있습니다.

class Range

  def each_reverse(&block)
    self.to_a.reverse.each(&block)
  end

end

하지만 저는 객체 지향적인 접근법보다는 순수한 루비를 가르치고 싶습니다.저는 거꾸로 반복하고 싶습니다.

  • 배열을 생성하지 않고(0..1000000000)
  • 모든 범위에서 작업(예: 정수가 아닌 문자열)
  • 별도의 객체 지향 전력을 사용하지 않음(즉, 클래스 수정 없음)

나는 이것이 정의하지 않고는 불가능하다고 믿습니다.pred메서드, 즉 이 메서드를 사용하도록 Range 클래스를 수정하는 것입니다.만약 당신이 이것을 할 수 있다면 저에게 알려주십시오, 그렇지 않으면 실망스럽지만 불가능한 것에 대한 확인은 감사하겠습니다.아마도 Ruby 1.9는 이것을 해결할 것입니다.

(시간을 내어 이 문서를 읽어 주셔서 감사합니다.

둘 다 필요한 경우 각_with_index를 사용합니다.

ary.each_with_index { |val, idx| # ...

다른 답변들은 괜찮지만, 저는 다른 한 가지를 지적하고 싶었습니다. 배열은 정렬된 반면 해시는 1.8에 없습니다. (Ruby 1.9에서 해시는 키 삽입 순서로 정렬됩니다.)따라서 1.9 이전 버전에서는 항상 명확한 순서가 있는 어레이와 동일한 방식으로 해시를 반복하는 것은 의미가 없습니다.저는 PHP 연관 배열의 기본 순서가 무엇인지 모르지만(분명히 제 구글 푸는 그것을 알아낼 만큼 강하지 않습니다), 연관 배열의 순서가 정의되지 않은 것처럼 보이기 때문에 일반 PHP 배열과 PHP 연관 배열이 이 맥락에서 "동일한" 것이라고 어떻게 생각할 수 있는지 모르겠습니다.

그런 만큼 루비의 방식이 제게는 더 명확하고 직관적으로 보입니다.:)

여기 당신의 질문에 나열된 네 가지 옵션이 통제의 자유에 따라 배열되어 있습니다.필요한 항목에 따라 다른 항목을 사용하는 것이 좋습니다.

  1. 값을 간단히 살펴봅니다.

    array.each
    
  2. 인덱스를 간단히 살펴봅니다.

    array.each_index
    
  3. 인덱스 + 인덱스 변수를 살펴봅니다.

    for i in array
    
  4. 루프 카운트 + 인덱스 변수 제어:

    array.length.times do | i |
    

배열과 해시에 대해 동일한 작업을 일관되게 수행하려고 하면 코드 냄새일 수 있지만, 일관된 행동을 찾고 있다면 코드가 있는 하프 원숭이 패처로 낙인찍힐 위험이 있습니다.:

class Hash
    def each_pairwise
        self.each { | x, y |
            yield [x, y]
        }
    end
end

class Array
    def each_pairwise
        self.each_with_index { | x, y |
            yield [y, x]
        }
    end
end

["a","b","c"].each_pairwise { |x,y|
    puts "#{x} => #{y}"
}

{"a" => "Aardvark","b" => "Bogle","c" => "Catastrophe"}.each_pairwise { |x,y|
    puts "#{x} => #{y}"
}

저는 해시를 사용하여 (캠핑마카비에서) 메뉴를 만들려고 했습니다.

각 항목에는 메뉴 레이블과 URL의 두 가지 요소가 있으므로 해시가 올바른 것처럼 보였지만 'Home'의 '/' URL은 항상 마지막에 나타나므로(해시에 예상한 대로) 메뉴 항목이 잘못된 순서로 표시되었습니다.

배열을 사용each_slice작업 수행:

['Home', '/', 'Page two', 'two', 'Test', 'test'].each_slice(2) do|label,link|
   li {a label, :href => link}
end

각 메뉴 항목(: CSS ID 이름)에 대한 추가 값을 추가하는 것은 슬라이스 값을 증가시키는 것을 의미합니다.따라서 해시와 마찬가지로 원하는 개수의 항목으로 구성된 그룹을 사용됩니다.완벽하네요.

그래서 이것은 무심코 해결책을 암시해 준 것에 대한 감사의 말입니다!

분명하지만 다음과 같이 말할 가치가 있습니다.배열의 길이가 슬라이스 값으로 구분되는지 확인하는 것이 좋습니다.

Rails와 같이 열거 가능한 믹스인을 사용하면 나열된 php 스니펫과 유사한 작업을 수행할 수 있습니다.ach_slice 메서드를 사용하여 해시를 평평하게 만듭니다.

require 'enumerator' 

['a',1,'b',2].to_a.flatten.each_slice(2) {|x,y| puts "#{x} => #{y}" }

# is equivalent to...

{'a'=>1,'b'=>2}.to_a.flatten.each_slice(2) {|x,y| puts "#{x} => #{y}" }

원숭이 패치가 덜 필요합니다.

그러나 재귀 배열이나 배열 값이 있는 해시가 있는 경우에는 문제가 발생합니다.루비 1.9에서 이 문제는 재발의 깊이를 지정하는 평탄화 방법에 대한 매개 변수로 해결됩니다.

# Ruby 1.8
[1,2,[1,2,3]].flatten
=> [1,2,1,2,3]

# Ruby 1.9
[1,2,[1,2,3]].flatten(0)
=> [1,2,[1,2,3]]

이것이 코드 냄새인지에 대한 질문에 대해서는 잘 모르겠습니다.보통 제가 어떤 것에 대해 반복하기 위해 몸을 뒤로 젖혀야 할 때 저는 뒤로 물러나고 제가 문제를 잘못 공격하고 있다는 것을 깨달았습니다.

Ruby 2.1에서는 각_with_index 메서드가 제거됩니다.대신 각_index를 사용할 수 있습니다.

예:

a = [ "a", "b", "c" ]
a.each_index {|x| print x, " -- " }

생성물:

0 -- 1 -- 2 --

올바른 방법은 여러분이 가장 편안하게 느끼고 여러분이 원하는 것을 하는 것입니다.프로그래밍에서 '올바른' 한 가지 방법은 거의 없으며, 더 자주 여러 가지 방법을 선택할 수 있습니다.

만약 여러분이 특정한 방법으로 일을 하는 것이 편하다면, 그것이 효과가 없는 한, 그냥 하세요 - 그러면 더 나은 방법을 찾아야 할 때입니다.

예를 들어 파서, JSON 파일 읽기 등에서 종종 발생하는 중첩 해시 및 어레이 구조를 처리하는 경우 어레이와 해시를 모두 반복하는 동일한 방법을 사용하는 것이 좋습니다.

아직 언급되지 않은 한 가지 현명한 방법은 표준 라이브러리 확장의 Ruby Facets 라이브러리에서 수행되는 방법입니다.여기서:

class Array

  # Iterate over index and value. The intention of this
  # method is to provide polymorphism with Hash.
  #
  def each_pair #:yield:
    each_with_index {|e, i| yield(i,e) }
  end

end

이미 있습니다. 별칭:Hash#each그래서 이 패치 이후에, 우리는 또한.Array#each_pair또한 해시와 어레이를 모두 사용할 수 있도록 호환적으로 반복할 수 있습니다..Array#each_with_index는 에비 블록인 반습니다었전되수와 있습니다.Hash#each사용 예:

my_array = ['Hello', 'World', '!']
my_array.each_pair { |key, value| pp "#{key}, #{value}" }

# result: 
"0, Hello"
"1, World"
"2, !"

my_hash = { '0' => 'Hello', '1' => 'World', '2' => '!' }
my_hash.each_pair { |key, value| pp "#{key}, #{value}" }

# result: 
"0, Hello"
"1, World"
"2, !"

언급URL : https://stackoverflow.com/questions/310634/what-is-the-right-way-to-iterate-through-an-array-in-ruby

반응형