Ruby 集合家族之数组(Array)

2019-08-19  本文已影响0人  ibob2012

创建数组

和其他动态语言创建相似。

>> a = [1, 2, 3]

=> [1, 2, 3]

>> a.class

=> Array

>> a.length

=> 3

>> a.size

=> 3

>> a[2]

=> 3

>> a << 4

=> [1, 2, 3, 4]

>> a

=> [1, 2, 3, 4]

1

2

3

4

5

6

7

8

9

10

11

12

13

14

其中类型不必相同,可以同时是 String 、Number 等

?> a = [1, "Grac Kanil", [2, 3]]

=> [1, "Grac Kanil", [2, 3]]

>>

?> a << true

=> [1, "Grac Kanil", [2, 3], true]

>> a << 3.14

=> [1, "Grac Kanil", [2, 3], true, 3.14]

1

2

3

4

5

6

7

一切皆对象,当然数组跑不了这个范畴

?> a = Array.new([1, "Hello", 2])

=> [1, "Hello", 2]

1

2

数组创建可以传参数,提前申请控件,但是数组是动态的,如果传入数组,会创建包含 nil 的数组。nil 也是一个对象,所以再追加,会在 nil 之后添加。当然可以快速传入默认值,占位数组。

?> a = Array.new(3)

=> [nil, nil, nil]

>>

?> a = Array.new(3, 1)

=> [1, 1, 1]

>>

?>

?> a = Array.new(3)

=> [nil, nil, nil]

>>

?> a << 3

=> [nil, nil, nil, 3]

?> a.size

=> 4

1

2

3

4

5

6

7

8

9

10

11

12

13

14

切割字符串为数组

scan 方法

>> s = "This is a test string."

=> "This is a test string."

>> s.scan(/\w/).join(",")

=> "T,h,i,s,i,s,a,t,e,s,t,s,t,r,i,n,g"

?> s.scan(/\b\w*\b/)

=> ["This", "", "is", "", "a", "", "test", "", "string", ""]

1

2

3

4

5

6

split 方法

>> s = "This is a test string."

=> "This is a test string."

?> s.split(" ")

=> ["This", "is", "a", "test", "string."]

>> s.split(" ").inspect

=> "[\"This\", \"is\", \"a\", \"test\", \"string.\"]"

?> s.split(/\s+/)

=> ["This", "is", "a", "test", "string."]

>> s.split(/\s+/).inspect

=> "[\"This\", \"is\", \"a\", \"test\", \"string.\"]"

1

2

3

4

5

6

7

8

9

10

11

% 来实现的语法捷径

?> est = "est"

=> "est"

>> %W{This is a t#{est} string.}

=> ["This", "is", "a", "test", "string."]

>>

?> %w{This is a t#{est} string.}

=> ["This", "is", "a", "t\#{est}", "string."]

1

2

3

4

5

6

7

数组越界问题

很多语言访问不存在的索引,会抛出数组越界异常,但 ruby 中不会,会返回 nil 哦

?> a = []

=> []

>> a[4]

=> nil

1

2

3

4

cool!��

以上是读,如果写入呢?

?> a

=> []

>> a[3] = "Grac"

=> "Grac"

>> a

=> [nil, nil, nil, "Grac"]

>> a[7] = "Kanil"

=> "Kanil"

>>

?> a

=> [nil, nil, nil, "Grac", nil, nil, nil, "Kanil"]

1

2

3

4

5

6

7

8

9

10

11

so cool!

在很多语言中,如果你的索引值小于 0 呢,又会怎样?

?> a = [1, 2, 3]

=> [1, 2, 3]

>>

?> a[-1]

=> 3

>>

?> a[-4]

=> nil

1

2

3

4

5

6

7

8

wonderful!

数组分类

表示数组前两个元素的多种表示方法

?> strings = %w{a b c d e f g}

=> ["a", "b", "c", "d", "e", "f", "g"]

>>

?> strings[0..1]

=> ["a", "b"]

>> strings[0...1]

=> ["a"]

>> strings[0...2]

=> ["a", "b"]

>> strings[0,2]

=> ["a", "b"]

>> strings[-7,2]

=> ["a", "b"]

>> strings[-7..-6]

=> ["a", "b"]

>> strings[-7...2]

=> ["a", "b"]

>> strings[-7..1]

=> ["a", "b"]

>> strings[0..-6]

=> ["a", "b"]

>> strings[0...-5]

=> ["a", "b"]

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

进阶思考

>> (0..1).class

=> Range

?> strings.[](0..1)

=> ["a", "b"]

>> strings.[](Range.new(0,1))

=> ["a", "b"]

1

2

3

4

5

6

有趣的 numerouno

➜  ~ gem install numerouno

Fetching: numerouno-0.2.0.gem (100%)

Successfully installed numerouno-0.2.0

Parsing documentation for numerouno-0.2.0

Installing ri documentation for numerouno-0.2.0

Done installing documentation for numerouno after 0 seconds

1 gem installed

➜  ~ irb --simple-prompt

?> require 'numerouno'

=> true

>>

?> "sixty one".as_number

=> 61

# 为数组添加英文索引

?> class EnglishArray < Array

>>  def [](idx)

>>    if String === idx

>>      self.at(idx.as_number)

>>    end

>>  end

>> end

=> :[]

>>

?> array = EnglishArray.new([1, 2, 3, 4])

=> [1, 2, 3, 4]

>>

?> array["one"]

=> 2

>> array["three"]

=> 4

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

Ruby 数组的万能结构

可以将数组作为栈。其功能和 Python list 相似,使用 pop 和 push 方法。

?> a = []

=> []

>> a.push(3)

=> [3]

>> a.push("Grac")

=> [3, "Grac"]

>>

?> a.push("Kanil")

=> [3, "Grac", "Kanil"]

>>

?>

?> a.pop

=> "Kanil"

>> a.pop

=> "Grac"

>> a.pop

=> 3

>> a

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

队列

队列,即先进先出

?> a = []

=> []

>> a.push(1)

=> [1]

>> a.push(2)

=> [1, 2]

>> a.push(3)

=> [1, 2, 3]

>> a.shift

=> 1

>> a.shift

=> 2

>> a.shift

=> 3

>> a

=> []

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

还可以使用 unshift 队首加入新元素

?> a = []

=> []

>> a.push(1)

=> [1]

>> a.unshift(2)

=> [2, 1]

>> a.unshift(3)

=> [3, 2, 1]

1

2

3

4

5

6

7

8

使用 delete 删除任意位置元素

?> a = [1, 2, 3]

=> [1, 2, 3]

>> a.delete(2)

=> 2

>> a

=> [1, 3]

1

2

3

4

5

6

集合

?> [1, 2, 3] + [4, 5, 6]

=> [1, 2, 3, 4, 5, 6]

?> [1, 2, 3] + [2, 3]

=> [1, 2, 3, 2, 3]

>> [1, 2, 3].concat([4, 5, 6])

=> [1, 2, 3, 4, 5, 6]

>> ["a", 1, 2, 3, "b"] - ["a", "b"]

=> [1, 2, 3]

>> [1, 2, 4] & [1, 2, 3]

=> [1, 2]

>> [1, 2, 4] | [1, 2, 3]

=> [1, 2, 4, 3]

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

Ruby 数组常用方法

检查数组是否为空

>> a = []

=> []

>> a.empty?

=> true

1

2

3

4

移动元素

# 转置

?> [1, 2, 4].reverse

=> [4, 2, 1]

# 向左移动一

?> [1, 2, 4].rotate

=> [2, 4, 1]

# 向右移动一

?> [1, 2, 4].rotate(-1)

=> [4, 1, 2]

1

2

3

4

5

6

7

8

9

10

11

安全提示

?> a = [1, 2, 3]

=> [1, 2, 3]

>> a.freeze

=> [1, 2, 3]

>> a << 4

RuntimeError: can't modify frozen Array

    from (irb):85

    from /Users/gekang/.rvm/rubies/ruby-2.2.4/bin/irb:11:in `<main>'

1

2

3

4

5

6

7

8

数组的 join 方法,将元素都链接为字符串

?> a = [1, 2, "Grac", "Kanil"]

=> [1, 2, "Grac", "Kanil"]

>>

?> a.join

=> "12GracKanil"

1

2

3

4

5

当然,可以传入参数

?> a.join(",")

=> "1,2,Grac,Kanil"

1

2

删除嵌套

?> [1, [2, 3], [4, ["a", nil]]].flatten

=> [1, 2, 3, 4, "a", nil]

>>

?> [1, [2, 3], [4, ["a", nil]]].flatten(1)

=> [1, 2, 3, 4, ["a", nil]]

1

2

3

4

5

删除副本

?> [4, 1, 2, 3, 1, 4].uniq

=> [4, 1, 2, 3]

1

2

检查是否包含某元素

?> a = [1, "a", 2]

=> [1, "a", 2]

>> a.include? "a"

=> true

>> a.include? 1

=> true

>> a.include?(1)

=> true

1

2

3

4

5

6

7

8

分割数组

?> a = [1, 2, 3, 4, 5, 6]

=> [1, 2, 3, 4, 5, 6]

>> a.first

=> 1

>> a.last

=> 6

>> a.first(3)

=> [1, 2, 3]

>> a.last(4)

=> [3, 4, 5, 6]

1

2

3

4

5

6

7

8

9

10

统计数组中某元素的个数

?> a = [4, 1, 2, 3, 1, 4]

=> [4, 1, 2, 3, 1, 4]

>> a.count 4

=> 2

1

2

3

4

查询数组所有方法

?> Array.methods

=> [:[], :try_convert, :allocate, :new, :superclass, :freeze, :===, :==, :<=>, :<, :<=, :>, :>=, :to_s,

:inspect, :included_modules, :include?, :name, :ancestors, :instance_methods, :public_instance_methods, :protected_instance_methods, :private_instance_methods, :constants, :const_get, :const_set,

:const_defined?, :const_missing, :class_variables, :remove_class_variable, :class_variable_get,

:class_variable_set, :class_variable_defined?, :public_constant, :private_constant, :singleton_class?,

:include, :prepend, :module_exec, :class_exec, :module_eval, :class_eval, :method_defined?,

:public_method_defined?, :private_method_defined?, :protected_method_defined?, :public_class_method, :private_class_method, :autoload, :autoload?, :instance_method, :public_instance_method, :nil?, :=~,

:!~, :eql?, :hash, :class, :singleton_class, :clone, :dup, :itself, :taint, :tainted?, :untaint,

:untrust, :untrusted?, :trust, :frozen?, :methods, :singleton_methods, :protected_methods,

:private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap,

:send, :public_send, :respond_to?, :extend, :display, :method, :public_method, :singleton_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :equal?, :!, :!=, :instance_eval,

:instance_exec, :__send__, :__id__]

1

2

3

4

5

6

7

8

9

10

11

12

迭代

迭代可以说是 Ruby 的一大亮点,我觉得 Objective-C 中的迭代就很少使用,比较笨重,更多的会想到写一个 for 循环,然而,Ruby 并不会,优雅的迭代使用起来比较顺手。

each

Ruby 中迭代的核心应该就是 each 方法了

?> a = ["This", "is", "a", "test", "string"]

=> ["This", "is", "a", "test", "string"]

>>

?> a.each {|s| puts s.cap} # Tab 键可以联想

s.capitalize  s.capitalize!  s.captures

?> a.each { |s| puts s.capitalize }

This

Is

A

Test

String

=> ["This", "is", "a", "test", "string"]

1

2

3

4

5

6

7

8

9

10

11

12

13

还有 reverse_each 反向迭代

?> a = ["This", "is", "a", "test", "string"]

=> ["This", "is", "a", "test", "string"]

>> a.reverse_each { |s| puts s.up }

s.upcase  s.upcase!  s.update  s.upto

>> a.reverse_each { |s| puts s.upcase }

STRING

TEST

A

IS

THIS

=> ["This", "is", "a", "test", "string"]

1

2

3

4

5

6

7

8

9

10

11

如果你需要索引,当然也给你准备好了当前处理的索引 each_with_index

>> a = ["This", "is", "a", "test", "string"]

=> ["This", "is", "a", "test", "string"]

>> a.each_with_index { |s, index| puts "#{index} is #{s}" }

0 is This

1 is is

2 is a

3 is test

4 is string

=> ["This", "is", "a", "test", "string"]

1

2

3

4

5

6

7

8

9

如果你需要迭代数组中某一部分,可以使用分割数组

?> a = ["This", "is", "a", "test", "string"]

=> ["This", "is", "a", "test", "string"]

>> a[0..2]

=> ["This", "is", "a"]

>> a[0..2].each {|s| puts s}

This

is

a

=> ["This", "is", "a"]

1

2

3

4

5

6

7

8

9

也可以使用 Range 来实现

?> a = ["This", "is", "a", "test", "string"]

=> ["This", "is", "a", "test", "string"]

>>

?> (0..2).each {|i| puts a[i]}

This

is

a

=> 0..2

1

2

3

4

5

6

7

8

map 或 collect

>> a = [1, 2, 3]

=> [1, 2, 3]

>> a.map { |i| i + 1 }

=> [2, 3, 4]

1

2

3

4

如果只是让每一个元素调用方法,不关心每个元素的值时,可以使用快捷写法

>> a = [1, 2, 3]

=> [1, 2, 3]

>> a.map(&:to_f)

=> [1.0, 2.0, 3.0]

1

2

3

4

#map 不改变原来的数组,而是会生成新的数组,如果需要修改原数组,需要使用 #map! 方法

>> a = [1, 2, 3]

=> [1, 2, 3]

>> a.map(&:to_f)

=> [1.0, 2.0, 3.0]

>>

?> a

=> [1, 2, 3]

>> a.map!(&:to_f)

=> [1.0, 2.0, 3.0]

>> a

=> [1.0, 2.0, 3.0]

1

2

3

4

5

6

7

8

9

10

11

#map 和 #collect 相同,可以互换使用

?> a = [1, 2, 3]

=> [1, 2, 3]

>> a.map(&:to_f)

=> [1.0, 2.0, 3.0]

>> a.collect(&:to_f)

=> [1.0, 2.0, 3.0]

————————————————

版权声明:本文为CSDN博主「GracKanil」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/grackanil/article/details/81869817

上一篇下一篇

猜你喜欢

热点阅读