关于迭代器有趣的小故事
时间:6月15日晚上7点 地点:电影院 人物:小明、小王、售票员、观众、奇怪的人
周末的夜晚,小明和小王兴致冲冲地决定去电影院看一场热映的电影。两人来到电影院,期待着一个美好的观影体验。
进入电影院大厅,他们看到售票员正忙碌地接待观众,颇具亲和力的微笑让人感到温暖。两人排队等候时,售票员发现了一个身着怪异服装的奇怪人,他手里拿着一只大大的气球。
“先生,请购票后入场。”售票员礼貌地提醒道。
“哎呀,我只是想带着气球看电影,没关系吧?”奇怪人有些局促地说。
“当然可以,但是请购票后再进场,谢谢。”售票员微笑回应。
奇怪人犹豫了一下,最终买了一张电影票,满足地走向电影厅。小明和小王感叹售票员的细心和耐心,为了让每个人都能体验到电影的乐趣,售票员竭尽所能。
正当小明和小王选择座位时,一位观众走到售票窗口,表情不满:“这场电影真是太烂了,我要退票!”售票员面带微笑地解释:“很抱歉,已经开始放映的电影无法退票,但我们会尽量为您提供更好的服务。”
见售票员的耐心和专业态度,原本愤怒的观众也渐渐冷静了下来,领着一份小礼品转而离去。
电影进行到一半,小偷突然在影厅内活动,引起一片骚动。小明看到了售票员急切的目光,明白他需要帮助。
“小王,我们去帮助售票员,阻止小偷!”小明毫不犹豫地说道。
小王点头,两人快速走到售票员身边。在售票员的指引下,他们成功地制止了小偷,把他交给了电影院的工作人员。
电影结束后,小明和小王深深地感慨:这场电影之旅虽然充满了波折,但售票员的细心、耐心和专业素养却让整个经历更加有趣和难忘。
在离开电影院时,小明对小王说:“这位售票员不仅是卖票的,更是一位懂得服务艺术的高手。他的微笑和耐心不仅让每位观众感到愉悦,还让整个电影院充满了温馨的氛围。”
小王附和道:“是啊,这次电影之旅不仅让我们欣赏到好片,还让我们见识到了一位服务至上的售票员,真是太棒了!”
迭代器模式概述
迭代器模式是一种行为设计模式,它提供一种顺序访问集合对象元素的方法,而不需要暴露集合的内部表示。通过使用迭代器模式,可以在不知道集合底层结构的情况下遍历集合中的元素。
关键元素
-
迭代器(Iterator): 定义访问和遍历元素的接口,包括获取下一个元素、判断是否还有元素等方法。
-
具体迭代器(ConcreteIterator): 实现迭代器接口,负责管理遍历集合的当前位置,并实现具体的遍历逻辑。
-
集合(Aggregate): 定义创建迭代器对象的接口,可以是抽象类或接口。
-
具体集合(ConcreteAggregate): 实现集合接口,负责创建具体迭代器对象。
工作原理
- 客户端通过集合接口获取迭代器对象。
- 迭代器负责跟踪遍历集合的状态。
- 客户端使用迭代器的方法遍历集合元素。
示例代码(使用 Golang)
package main
import "fmt"
// 迭代器接口
type Iterator interface {
HasNext() bool
Next() interface{}
}
// 集合接口
type Aggregate interface {
CreateIterator() Iterator
}
// 具体迭代器
type ConcreteIterator struct {
data []interface{}
index int
}
func (ci *ConcreteIterator) HasNext() bool {
return ci.index < len(ci.data)
}
func (ci *ConcreteIterator) Next() interface{} {
item := ci.data[ci.index]
ci.index++
return item
}
// 具体集合
type ConcreteAggregate struct {
data []interface{}
}
func (ca *ConcreteAggregate) CreateIterator() Iterator {
return &ConcreteIterator{data: ca.data}
}
func main() {
// 创建具体集合
aggregate := &ConcreteAggregate{data: []interface{}{"A", "B", "C", "D", "E"}}
// 获取迭代器
iterator := aggregate.CreateIterator()
// 遍历集合
for iterator.HasNext() {
item := iterator.Next()
fmt.Println(item)
}
}
这个示例中,ConcreteAggregate 实现了集合接口,负责创建具体迭代器 ConcreteIterator。客户端通过集合接口获取迭代器对象,然后使用迭代器的方法遍历集合元素。这样,无论集合的内部结构如何变化,客户端都不受影响。
Golang中的range
如果上面的故事和设计模式没有看懂也没有关系,现在许多语言已经将这种模式内化了,使用起来非常的简单,只看下面的例子就行;如果前面都能看懂就最好了。
在Go语言中,range 关键字用于迭代数组、切片、字符串、map 等数据结构。range 在循环中提供了对数据结构元素的访问,使得遍历变得更加简洁和直观。
range 是Go语言中一种强大的迭代工具,简化了对数据结构的遍历操作。
-
计算切片元素的和:
nums := []int{2, 3, 4} sum := 0 for _, num := range nums { sum += num } fmt.Println("sum:", sum)在这里,使用
range遍历了切片nums中的元素,并将其累加到sum变量中,最后打印总和。 -
查找切片中元素的索引:
for i, num := range nums { if num == 3 { fmt.Println("index:", i) } }在这段代码中,
range返回了切片nums中的索引和值,通过判断值是否为3,找到了对应的索引并打印。 -
遍历映射(map):
kvs := map[string]string{"a": "apple", "b": "banana"} for k, v := range kvs { fmt.Printf("%s -> %s\n", k, v) }这里使用
range遍历了映射kvs中的键值对,并打印键值对。 -
仅遍历映射的键:
for k := range kvs { fmt.Println("key:", k) }当仅需要映射的键时,可以省略值的接收。
-
遍历字符串:
for i, c := range "go" { fmt.Println(i, c) }使用
range遍历了字符串 "go" 中的 Unicode 字符,打印了字符的索引和Unicode码点。
完整练习代码:
package main
import "fmt"
func main() {
nums := []int{2, 3, 4}
sum := 0
for _, num := range nums {
sum += num
}
fmt.Println("sum:", sum)
for i, num := range nums {
if num == 3 {
fmt.Println("index:", i)
}
}
kvs := map[string]string{"a": "apple", "b": "banana"}
for k, v := range kvs {
fmt.Printf("%s -> %s\n", k, v)
}
for k := range kvs {
fmt.Println("key:", k)
}
for i, c := range "go" {
fmt.Println(i, c)
}
}