2016-11-01 09:37:50 mydo 阅读数 1963

随机化数组元素或称为”洗牌”,是比较常用的算法,常常应用到一些游戏中.

在Swift中我们可以有很多种选择.这里我只说两种:一种是扩展Array的功能,另外一种是利用GameplayKit中的内置方法.

首先上代码:

extension Array{
    mutating func shuffle(){
        for i in 0..<(count-1){
            let j = Int(arc4random_uniform(UInt32(count-i)))+i

                swap(&self[i], &self[j])

        }
    }
}

在Xcode8.0的playground中运行,咦,怎么出错了!?

fatal error: swapping a location with itself is not supported

其原因为swip不能交换同一个地址的元素,所以你在交换之前要做判断,在swap(&self[i], &self[j])一句用if语句包围住即可:

if i != j{
    swap(&self[i], &self[j])
}

这种方法将会改变数组对象本身.

下面我们import GameplayKit后,利用GameplayKit中的arrayByShufflingObjects方法也可以完成随机数组元素的任务,不过这次你会得到一个随机后数组的拷贝,原来的数组对象保持不变:

var ary = Array(1..<10)
var aryCopy = ary
ary.shuffle()
let shuffleAry = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: aryCopy)
aryCopy
2017-08-21 16:53:08 appleLg 阅读数 5609

交换数组中两个元素位置

方法一:苹果提供的swap方法

代码

var originArrayOne = [2,3,4]
print("originArrayOne排序前:\(originArrayOne)")
//交换第0个元素和第2个元素位置
//方法一
swap(&originArrayOne[0], &originArrayOne[2])
print("originArrayOne排序后:\(originArrayOne)\n")

效果
这里写图片描述

方法二: 使用元祖

代码:

//方法二
var originArrayTwo = [2,3,4]
print("originArrayTwo排序前:\(originArrayTwo)")
(originArrayTwo[0],originArrayTwo[2]) = (originArrayTwo[2],originArrayTwo[0])
print("originArrayTwo排序后:\(originArrayTwo)\n")

效果
这里写图片描述

方法三: 自定义swap(方法一的实现)

代码:

//方法三(方法一的实现)
var originArrayThree = [2,3,4]
print("originArrayThree排序前:\(originArrayThree)")
mySwap(&originArrayThree[0],&originArrayThree[2])
print("originArrayThree排序后:\(originArrayThree)")
func mySwap<T>(_ i : inout T, _ j : inout T){
    var temp = i
    i = j
    j = temp
}

这里写图片描述

还有更多更好的方法请联系我

2019-05-23 16:18:28 weixin_43883776 阅读数 313

数组
1、初始化一个空数组
我个人习惯于使用 Array.init() 初始化一个空字符串
在这里插入图片描述
2、初始化非空数组 并 遍历
在这里插入图片描述

PS :Any 表示数组中的元素可以是任意类型的元素 AnyObject表示对象类型,由于Str类型属于结构体类型,所以,此处不能使用AnyObject。
3、增加元素
1️⃣、在指定位置加入在这里插入图片描述
在 第3位置加入一个元素
2️⃣、在结尾加入
在这里插入图片描述
4、删除元素
1️⃣、删除首位置元素
在这里插入图片描述
2️⃣、移除指定位置元素
在这里插入图片描述
3️⃣、移除指定元素
swift 似乎没有提供直接移除某个元素的 方法,但是官方提供一个思路,来解决这个问题,也是大家都能想到的方法在这里插入图片描述
定义一个外部变量,记录一下要移除的位置。
4️⃣、移除第一个和最后一个
PS 获取数组第一个或最后一个元素
在这里插入图片描述

在这里插入图片描述
5️⃣、按照指定区间移除元素
在这里插入图片描述
移除了2 3 4 位元素

5、将两个字符串合并
在这里插入图片描述
6、交换数组元素
交换了第3位和第6位元素

字典
1️⃣、初始化空字符串和非空字符串
在这里插入图片描述
在这里插入图片描述
2️⃣、遍历字典
字典的遍历与OC中的遍历稍有不同,我们可以轻松地获取到key和value
字典的遍历是无序的

在这里插入图片描述
3️⃣、增加键值对或修改键值对 updateValue
在这里插入图片描述

在这里插入图片描述
PS 请注意 updateValue 方法是有返回值的,对已经存在的键值对,该方法返回修改前的 value 的值,对于不存在的键值对则返回nil。返回值类型为“?”类型,想要输出则需要转型。对于nil 不能使用转型。
在这里插入图片描述
4️⃣、移除键值对
在这里插入图片描述

removeValue  方法是有返回值的,返回该key对应的value,

还有一种移除方法 remove(at: <#T##Dictionary<Int, String>.Index#>)
字典通过.index(forKey: <#T##Int#>)方法可以获取到index ,通过 该方法,可以获取到 你即将要移除的键值对。如下图
在这里插入图片描述
在这里插入图片描述
当然我们也可以分别获取到key和value 值
在这里插入图片描述

我是磊怀 2849765859 QQ

2015-08-01 21:59:39 abc649395594 阅读数 4062

集合

集合的定义

Swift中提供了两种数据结构用于存放数据的集合,分别是数组(Array)和字典(Dictionary)。他们的主要区别在于数组中的元素由下标确定,而字典中的数据的值由数据的键(Key)决定。以下我们认为集合就是数组或字典。

集合的可变性

我们可以定义一个集合常量或者集合变量。一旦定义为常量,就意味着集合的长度、内容和顺序都不能再修改了。比如,定义为常量的数组,不能再向其中添加新的元素。

数组的创建

由于swift中变量的创建遵循“ var 变量名:变量类型 ”的语法,因此数组的创建归根结底还是数组类型的定义。一共有三种方法来定义数组的类型:

var arrayOne:Array<Int> = [1,2,3]
println("arrayLong = \(arrayOne)")

var arrayTwo:[Int] = [1,2,3]
println("arrayShort = \(arrayTwo)")

var arrayThree = [1,2,3]
println("arrayThree = \(arrayThree)")

第一种是数组类型的完整定义,即Array关键字加上一对尖括号,括号内写上数组元素的类型。

第二种是数组类型的简化定义,即一对方括号内写上数组元素的类型。这与第一种定义方法完全等价。

在使用这两种方法定义数组的时候,一定要确保数组中每个元素类型相同,否则将会产生编译错误。

第三种运用了Swift的类型推导的特性。需要注意的是,数组的值由方括号组成,里面的元素用逗号隔开。如果方括号改成了圆括号,编译器不会报错(这将变成元组),所以千万要小心,避免莫名其妙的错误。

第三种方法除了书写简单之外,还有一种好处,即不必确保数组中每个元素类型相同。我们来通过代码看一看多个不同类型的元素出现在统一数组中会发生什么情况:

var arrayThree = [1,2,3]
println("arrayThree = \(arrayThree)")

var arrayMixed = [1,"abc",true, 1.5]
println("arrayMixed = \(arrayMixed)")//在这一行结束前设置断点
//在LLDB调试其中分别输入print arrayThree和print arrayMixed

可以得到如下结果

([Int]) $R0 = 3 values {
  [0] = 1
  [1] = 2
  [2] = 3
}

([NSObject]) $R1 = 4 values {
  [0] = 0x0000000000000137 Int64(1)
  [1] = "abc"
  [2] = 0x00007fff7255e8a8 {
    NSNumber = {
      NSValue = (null)
    }
  }
  [3] = 0x00000001006008a0 {
    NSNumber = {
      NSValue = (null)
    }
  }
}

因此不难发现,arrayMixed数组之所以可以添加多个类型的元素,是因为它被推导为Array< NSObject>类型。同样的,所以一旦数组的类型确定,就不能再插入不属于这个类型的的值。

在我阅读的教材上,作者特别提出,不指定类型的数组不能使用Array的append方法。但是经过我的测试,并没有这样的限制。有兴趣的读者可以自行测试,欢迎指正。

数组的访问与修改

数组长度

可以使用数组的只读属性count来获取数组长度:

var arrayThree = [1,2,3]
println("arrayThree.count = \(arrayThree.count)")

判断数组为空

可以使用数组的只读属性isEmpty来判断数组是否为空,当然通过判断count是否为0也可以达到同样的效果,不过代码略长一些。

var arrayThree = [1,2,3]
if !arrayThree.isEmpty{
    println("Array Three is not empty")
}

添加新元素

一共有两种方法可以在数组的尾部添加新元素:

//方法一,使用数组的append函数
var arrayThree = [1,2,3]
arrayThree.append(4)
println("arrayThree = \(arrayThree)")

//方法二,使用加法运算符
var arrayThree = [1,2,3]
arrayThree += [4]
println("arrayThree = \(arrayThree)")

无论使用哪种方法,都必须保证新添加的元素和数组类型相同。比如试图像arrayThree中添加元素’1.5’会导致编译错误。
可以看到,第二种方法的本质实际上是在两个数组对象之间调用加法运算符,得到的结果是两个数组拼接之后的结果。因此,第二种方法具有一个强大的功能,即向数组尾部添加多个元素。

还有一种通用的方法,即调用数组的insert(atIndex:)方法,在指定位置插入新元素。

var arrayThree = [1,2,3]
arrayThree.insert(4, atIndex: 2)
println("arrayThree = \(arrayThree)")

删除数组元素

可以调用数组的removeAtIndex()和removeLast()方法。

var arrayThree = [1,2,3]
var numberThree = arrayThree.removeAtIndex(2)
var numberTwo = arrayThree.removeLast()

这两个方法会返回被删除的元素的值,当然如果不需要知道,可以无视它的返回值,直接调用方法即可。

需要注意的一点是,removeAtIndex方法首先要判断下标是否越界,也就是说它会用到数组的长度。这意味着需要线性遍历数组,因此如果只需要移除数组的最后一个元素且数组长度很大时,应该使用removeLast()方法。

访问数组元素

了解了如何添加和删除元素,我们就要想办法把新加入的元素取出来看看了。通过数组下标可以访问指定位置的数组元素,语法与C语言相同。

var arrayThree = [1,2,3]
println("ArrayThree[2] = \(arrayThree[2])")

修改数组元素

下标不仅可以访问数组元素,还可以实现数组元素的修改。这和访问数组元素是非常类似的,只要交换等号两边变量的位置即可。

var arrayThree = [1,2,3]
var secondInt = arrayThree[1] //访问元素

var newSecond = 4
arrayThree[2] = newSecond //修改数组元素

不仅如此,还可以通过数组下标批量修改元素:

var arrayThree = [1,2,3]
var firstNumber = 1
var secondNumber = 2
arrayThree[0...1] = [firstNumber,secondNumber]

此时,等号的右侧必须是数组的字面量,而不能是一个数组变量。也就是说这样的写法是错误的:

var arrayThree = [1,2,3]
var newArray = [3,4]
var newSlice: ArraySlice<Int> = [3,4]
arrayThree[0...1] = newArray //错误。
arrayThree[0...1] = newSlice //正确

原因是左边的arrayThree[0…1]其实是一个SubArray,在Swift中它的类型叫做ArraySlice,即Int类型的数组切片,而右边是一个Array类型变量,根据Swift类型安全的特性,这样的操作自然是被禁止的。

如果左边的切片长度和右边的变量长度不一致会发生什么情况呢?不用过于担心,这不会产生任何错误。Swift会机智的帮我们解决这个问题。

var arrayOne:[Int] = [1,2,3]
var arrayTwo = [1,2,3]
var sliceOne:ArraySlice<Int> = [1,2,3]
var sliceTwo:ArraySlice<Int> = [1]
arrayOne[1...2] = sliceOne
arrayTwo[1...2] = sliceTwo
println("arrayOne = \(arrayOne)")
println("arrayTwo = \(arrayTwo)")

输出结果分别是:

arrayOne = [1, 1, 2, 3]
arrayTwo = [1, 1]

因此,如果变量长度超过切片长度,将会自动在切片位置后添加元素(如同arrayOne),相当于调用了数组的insert(atIndex:)方法若干次。同样地,如果变量长度少于切片长度,没有值的位置的元素自动被移除,后面的元素自动向前补上。相当于调用了数组的removeAtIndex()方法若干次。

虽然这样不会出现任何错误,不过出于逻辑严谨性考虑,应该避免等号两端变量长度不一样的情况。

数组遍历

之前我们介绍了数组的增删改操作,还缺少一个查找。也就是数组的遍历。在Swift中,除了像C语言那样定义一个下标变量,在for循环中遍历数组,还有两种方式遍历数组。

//方法一,使用for in循环快速遍历
var array = [1,2,3,2,1,32,99]
for number in array{
    println("number = \(number)")
}

通过观察输出结果可以发现,for in循环是按照从前向后的顺序遍历数组的。

//方法二:使用enumerate函数
var array = [1,2,3,2,1,32,99]
for (index, value) in enumerate(array){
    println("value = \(value)")
}

enumerate(array)方法的返回值是一个数组。数组中的每一个元素都是一个二元元组。第一个值是下标index,第二个值是元素的值。这种方法也是顺序遍历数组。

数组的初始化

在本章的开头,我们利用数组字面量来初始化一个数组。其实,数组还有其他的初始化方法。

首先类比字符串的构造方法var string = String(),我们可以得知数组的另外两种构造方法。

var arrayOne = [Int]()
var arrayTwo = Array<Int>()
println("第一个数组元素个数为:\(arrayOne.count)")
println("第二个数组元素个数为:\(arrayTwo.count)")

运行结果:

第一个数组元素个数为:0
第二个数组元素个数为:0

除此以外,数组还有一种特殊的构造方法,可以指定数组长度,在这种情况下还必须强制指定数组中每个元素的值。如果觉得没用的话,可以先设置为0,然后再修改。

var arrayThree = [Int](count: 5, repeatedValue: 0)
var arrayFour = Array<Int>(count: 5, repeatedValue: 0)
var arrayFiver = Array(count: 5, repeatedValue: 0)
print("第三个数组为:\(arrayThree)")
print("第四个数组为:\(arrayFour)")
print("第五个数组为:\(arrayFiver)")

得益于类型推导,第五种数组初始化方法也是合法的。但是之前的标准初始化方法不可以这么简化。输出结果如下:

第三个数组为:[0, 0, 0, 0, 0]
第四个数组为:[1, 1, 1, 1, 1]
第五个数组为:[2, 2, 2, 2, 2]

附录

查看完整专栏——《Swift轻松入门》

【Swift入门(一)——基本语法】
【Swift入门(二)——字符与字符串】
【Swift入门(三)——元组(Tuple)】
【Swift入门(四)——可选类型(Optionals)与断言(Assert)】
【Swift入门(五)——数组(Array)】
【Swift入门(六)——字典(Dictionary)】
【Swift入门(七)——结构体(Struct)】
【Swift入门(八)——功能强大的求余运算符】
【Swift入门(九)——String与Int、Double、Float等数字相互转换】
【Swift入门(十)——循环引用、弱引用和无主引用】
【Swift入门(十一)——类型转换与is、as操作】
【Swift入门(十二)——利用Extension添加逆序输出字符串方法】

2015-09-09 14:58:51 CODE_WORM 阅读数 6273


/*

编程环境: xcode 7.0 beta6

*/




/*---------------------------.数组的创建-------------------------*/

//[someType]  等同于 Array<someType>,都代表可以装有someType这种类型数据的数组,下边我只使用[someType]这种形式:


/*

1. 变量数组,常量数组

变量数组可以进行更改,对应OC可变数组:NSMutableArray,常量数组不可以进行修改, 对应OC不可变数组:NSArray

*/

var arr1_1:[Int]     //变量数组

let arr1_2: [Int]    //常量数组,可以不直接赋值, 但是当第一次赋值过后就不可以更改了


/*

2. 数组的创建你可以指定这个数组装有什么类型,如果你指定特定的类型, 那么这个数组只能装这个类型的数据,或者这个类型的子类的数据;

*/

let arr1_3: [String] = ["ab","cd"] //只能添加字符串类型


/*

3. 如果你不指定的类型, swift会有类型推断,根据你在等号右边赋的值来进行类型推断:

*/

//(1). 如果赋的值都是某个特定类型的数据,比如说都是[1, 2, 3], 那么类型推断为[Int];

var arr1_4 = [1,2, 3]    //这时arr1_4[Int]类型

arr1_4 = []              //这种情况, arr1_4依旧是[Int]类型


//(2). 如果你所赋的值都为NSObject类的对象或者继承与NSObject类的对象,或者String, Int, Double等一些基础类型, 那么swift将这个数组推断为[NSObject]类型;

let NSStr1_1: NSString ="NSString"

let arr1_5 = [1,"123", NSStr1_1]   //这时arr1_5[NSObject]类型


//(3). 如果数组中包含不止继承与NSObject类的数据(没有任何继承与任何类的对象),或者不继承与NSObject又不是基础类型数据,比如说Array Dictionary, swift将其推断为NSArray类型(原来是OC中的类型, swift中一样有这个类型, 实现了部分OC中的方法), NSArray这个类型可以和swift中的[Element]相互转换, [Element](这个涉及到泛型, 就是一个占位类型, 你往数组添加任何类型的数据都可以);

let arr1_6 = [1,"123", arr1_5]   //识别为NSArray类型

let arr1_7 = Array(arr1_6)        //将其转换为[Element]类型,注意[Element]这个类型不可以直接声明;

/*如果想得到一个,空的泛型数组可以这样写:*/

let arr1_8 = []             //这个时候识别为NSArray类型

var arr1_9 = Array(arr1_8//arr1_9就是一个空的[Element]类型的数组


//4. 创建一个有多个元素重复的数组

var arr1_10 = Array(count:3, repeatedValue: 1.3)

print(arr1_10)

/*打印结果

[1.3, 1.3, 1.3]  //含有3 1.3的数组

*/


//5. 通过两个数组相拼接的方式获取新数组

var arr1_11 = arr1_7 + arr1_9//等号后边两个数组必须是相同类型的数组,比如这两个都是泛型数组[Element]

print(arr1_11)

/*打印结果

[1, 123, (

1,

123,

NSString

)]

*/


//6. 通过 Array(arrayLiteral: <#T##Element...##Element#>)来创建数组:

var NSStr1_2: NSString ="NSString2"

let arr1_12 = Array(arrayLiteral:1, "123",1.23, NSStr1_2)     //这后边只能填NSObject类的对象或者继承与NSObject类的对象,以及Int, Double, String 一些基础类型,这时arr1_12被识别为[NSObject]类型


//7. 通过范围运算符 0...1来创建数组:

//0...1 表示 0 1 的开区间(0..<1表示0 1 的半开半闭区间,不包括1)

let arr1_13 = [0,1, 2, 3, 4, 5]

var arr1_14 = arr1_13[0...3]   //这个时候arr1_14ArraySlice类型(ArraySlice类型和Array类型很像,像截取数组的一部分的时候, 都会被识别为ArraySlice类型,可以被理解为迷你版的Array, Array ArraySlice 类型和可以相互转换)

var arr1_15 = Array(arr1_14)  //转换为Array<Int>类型




/*---------------------------.遍历数组-------------------------*/


//1 首先说一下如何查看数组的元素,以及获取数组的一些基础属性

var arr2_1 = [999,10, 99, 4]

//(1)首先说一下数组名[下标]的方式来访问或者修改数组元素 eg:

print(arr2_1[0])

/*打印结果

999

*/


arr2_1[0] =110

print(arr2_1)

/*修改后的打印结果

[110, 10, 99, 4]

*/


//(2)通过0...1(这个表示0 1 的开区间)的这种范围方式来访问数组:

print(arr2_1[0...1])

/*打印结果

[110, 10]

*/


//(3)获取数组某些特定位置的元素:

print(arr2_1.first)    //获取数组的第一个元素    打印结果: Optional(110)

print(arr2_1.last)     //获取数组的最后一个元素  打印结果: Optional(4)


//(4)获取数组元素的数量:

print(arr2_1.count)   //打印结果: 4


//2. for in 数组遍历

//(1)for in 遍历全部元素

for id in arr2_1 {

    print(id)

}

/*打印结果

999

10

99

4

*/


//(2)for in 遍历数组某一个区间的元素

for id in arr2_1[1...3]{

    print(id)

}

/*打印结果:

10

99

4

*/


//3. for 循环数组遍历

for var i =0; i < arr2_1.count; ++i {

    let id = arr2_1[i]

    print(id)

}

/*打印结果

999

10

99

4

*/


//4. 使用枚举法,进行遍历

for (a, b) inarr2_1.enumerate(){

    print("\(a) =\(b)")

}

/*打印结果

0 = 999

1 = 10

2 = 99

3 = 4

*/


//5. 模拟系统给出的枚举法遍历数组

var en = arr2_1.enumerate().generate()

var temp: (Int,Int)? = en.next()

while temp !=nil {

    print(temp!)

    temp = en.next()

}

/*打印结果

(0, 999)

(1, 10)

(2, 99)

(3, 4)

*/




/*---------------------------.给数组添加元素-------------------------*/

//1. 在数组的后边添加一个元素

var arr3_1 = ["hello"]

arr3_1.append("world")

print(arr3_1)

/*打印结果:

[hello, world]

*/


//2. 在数组的某个位置添加元素:

arr3_1.insert("my", atIndex:1)

print(arr3_1)

/*

[hello, my, world]

*/


//3.使用 +=给数组拼接另一个数组在老版本是可以使用 +=拼接一个元素的, 但这个版本把这个功能去掉了

arr3_1 += ["codeWorm","dear"]

print(arr3_1)

/*打印结果:

[hello, my, world, codeWorm, dear]

*/


//4. 在数组的某个index位置,添加一个相同类型的数组:

arr3_1.insertContentsOf(["123","456"], at:0)

print(arr3_1)

/*打印结果:

["123", "456", "hello", "my", "world", "codeWorm", "dear"]

*/




/*---------------------------.删除数组的元素-------------------------*/

var arr4_1 = [1,2, 3, 4, 5]


//1. 删除最后一个元素,返回值为被删除的元素

let remove1 = arr4_1.removeLast()

print(arr4_1)

/*打印结果

[1, 2, 3, 4]

*/


//2. 删除某个index的元素,返回值为被删除的元素

let remove2 = arr4_1.removeAtIndex(0)

print(arr4_1)

/*打印结果

[2, 3, 4]

*/


//3. 删除某个范围的元素

arr4_1.removeRange(Range(start:0, end: 1))

print(arr4_1)

/*打印结果

[3, 4]

*/


//4. 删除数组的所有元素,并且不保留数组所占的空间

arr4_1.removeAll()


//5. 删除数组的所有元素,但是所占的内存空间将被保留

arr4_1.removeAll(keepCapacity:true)




/*---------------------------.修改数组的元素-------------------------*/

var arr5_1 = [1,2, 3, 4, 5, 6,7]


//1. 可以用数组名[下标数]这种形式 来修改某个index的元素值

arr5_1[0] =99 //将第0个元素的值修改为99

print(arr5_1)

/*打印结果

[99, 2, 3, 4, 5, 6, 7]

*/



//2. 将数组某个范围的元素替换为后面的这段数组的元素,注意这个范围最大数不能超过数组的count - 1否则会运行时崩溃

arr5_1[1...3] = [100,101, 102]

print(arr5_1)

/*打印结果

[99, 100, 101, 102, 5, 6, 7]

*/


//3. 使用 arr5_1.replaceRange(<#T##subRange: Range<Int>##Range<Int>#>, with: <#T##C#>) 来替换元素, 这里第一个参数为范围, 第二个参数是要替换的数组或者表示数组的指针

arr5_1.replaceRange(Range(start:0, end: 4), with: [0,1, 2, 3, 4])

print(arr5_1)

/*打印结果

[0, 1, 2, 3, 4, 5, 6, 7]

*/


//replaceRange 替换UnsafeMutableBufferPointer数组的指针类型:

var arr5_2 = [999,1000, 1001]

var pointer = UnsafeMutableBufferPointer<Int>(start: &arr5_2, count:arr5_2.count)    //这是用来表示字符串的指针类型

arr5_1.replaceRange(0..<1, with: pointer)    //第一个参数range的另一种表现形式, 0 1 的半开半闭区间(0...1 表示0 1的开区间), 这里也就是表示, arr5_1的第0个元素替换成这个数组指针对应数组的元素

print(arr5_1)

/*打印结果

[999, 1000, 1001, 1, 2, 3, 4, 5, 6, 7]

*/





/*---------------------------.对于数组的一些基础的判断-------------------------*/


//1. 判断数组是否为空

var arr6_1: [Int] = []

print(arr6_1.isEmpty)//判断的前提是数组已经被实例化

/*打印结果

true

*/


//2. 判断数组是否包含某个元素:

var arr6_2 = ["hello","world", "I","am", "code"]

//(1)可以直接这么调用:

print(arr6_2.contains("hello"))

/*打印结果

true

*/

//(2) 可以使用闭包为参数进行判断

let isContain =arr6_2.contains { (obj) -> Boolin      //这个运行原理就是,编译器调用你的闭包,将数组内的元素顺次作为闭包的参数传入, 进行判断, 当然判断逻辑是你写的,直到闭包的返回值为true 或者将数组内的所有元素传参完毕闭包调用结束,否则继续传入下一个数组的元素作为参数调用这个闭包,如果闭包的返回值出现为true的情况,contains返回值为true,如果直到闭包调用完毕都没有出现true的情况,contains返回值为false

    if obj == "木哈哈" {

        return true

    }

    return false

}

//简写:

let isContainSam =arr6_2.contains{$0 =="木哈哈"}   //$0 就是第一个参数的意思, $1第二个, 多个参数同理, 当一个闭包只有一个return语句时, return可以省略

print(isContain)

/*打印结果

false

*/




/*---------------------------.数组分割为字符串, 字符串拼接数组-------------------------*/

//这个如果有OC基础就知道这个:

//1. 使用某个字符串来分割字符串,分割结果为数组:

let str7_1 = "www.baidu.com/www.v1.cn/haha"

let arr7_1 = str7_1.componentsSeparatedByString(".")

print(arr7_1)

/*打印结果

["www", "baidu", "com/www", "v1", "cn/haha"]

*/


//2. 使用NSCharacterSet类型来分割字符串:

let arr7_2 = str7_1.componentsSeparatedByCharactersInSet(NSCharacterSet(charactersInString:"./"))    //分别以. /来分割

print(arr7_2)

/*打印结果

["www", "baidu", "com", "www", "v1", "cn", "haha"]

*/


//3. 将数组拼接成字符串

let str7_2 = arr7_2.joinWithSeparator("我是 (空格)")

print(str7_2)

/*打印结果

www我是 (空格)baidu我是 (空格)com我是 (空格)www我是 (空格)v1我是 (空格)cn我是 (空格)haha

*/




/*---------------------------.数组的一些其他方法-------------------------*/


//1. sortInPlace 排序

var arr8_1 = [2,32, 1, 5, 3, 4]

//sortInPlace方法就是原来的sort方法

arr8_1.sortInPlace { (id1, id2) ->Bool in     //传入闭包的原理类似与将冒泡排序的排序准则传入,编译器来实现冒泡排序, 然后根据你的准则来判断是否交换元素位置, eg:

    if id1 > id2{

        return true

    }

    return false

}

//上边这个可以简写为:

//arr8_1.sortInPlace {$0 > $1}       //$0 就是第一个参数的意思, $1 第二个, 多个参数同理,当一个闭包只有一个return语句时, return可以省略

print(arr8_1)

/*打印结果

[32, 5, 4, 3, 2, 1]

*/


//2. reverse 翻转数组:

let arr8_2 = [9,6, 3, 0, 2, 4,5]

let arr8_3 = Array(arr8_2.reverse())

print(arr8_3)

/*打印结果:

[5, 4, 2, 0, 3, 6, 9]

*/


//3. filter 过滤数组:

let arr8_4 = [-5, -4, -3, -2,0, 1, 2, 3, 4,5, 6, 7, 8]

let arr8_5 = arr8_4.filter{$0 %2 == 0 && $0 >0//过滤出数组中的正偶数

//展开为:

//let arr8_5 = arr8_4.filter { (obj) -> Bool in

//    return obj % 2 == 0 && obj > 0

//}

print(arr8_5)

/*打印结果:

[2, 4, 6, 8]

*/


//4. map 遍历计算数组

let arr8_6 = [1,2, 3, 4, 5]

let arr8_7 = arr8_6.map{$0 *2} //通过计算形成新数组

print(arr8_7)

/*打印结果:

[2, 4, 6, 8, 10]

*/


//5. reduce 方法

let arr8_8 = [2.0 ,9.0]

let result8_1 = arr8_8.reduce(9.0) { (obj1, obj2) ->Double in

    return obj1/obj2

}

//reduce, 需要传一个初始值,这里传的是9.0, 第一次传入闭包两个参数分别为初始值本身 数组的第一个元素,第二次传的两个参数分别为, 第一次闭包的运算结果和数组的第二个元素,直到所有数组的元素全部被运算完毕, 最后一次调用闭包完毕返回的值为最终的值, 这里做的计算也就是: 9.0/2.0/9.0 = 0.5


//简写为:

//let result8_1 = arr8_8.reduce(9.0){$0/$1}    这里涉及到尾随闭包的知识, 在网上搜一下尾随闭包就知道怎么回事了


print(result8_1)

/*打印结果:

0.5

*/




/*---------------------------.数组拷贝-------------------------*/

/*

swift刚一出现的时候,数组是作为引用类型出现的, 虽然作为一个结构体,但是更像是类的对象的性质, 这可见数组的这个结构体的底层不单单是像C语言和OC中在栈区开辟空间去存储值类型那么简单,猜测也是要去堆区开辟空间的, 在后来更新版本中, Array取消了这样的性质,而是只作为值类型出现, 这样就让新学习swift的人来说不会有"为什么值类型还可以做引用的操作?"这样的困惑, 下面是一个eg:

*/

var arr9_1 = [1,2, 3]

var arr9_2 = arr9_1

arr9_2[0] =999

print("arr9_1 =\(arr9_1) arr9_2 =\(arr9_2)")

/*打印结果:

arr9_1 = [1, 2, 3] arr9_2 = [999, 2, 3]

*/


//可见现在的数组是一个值类型了!



交换数组两个元素

阅读数 2761

数组元素交换 swap

阅读数 2466

swift 泛型

阅读数 441