Swift学习内容精选(一)
Swift 可选(Optionals)类型
Swift 的可选(Optional)类型,用于处理值缺失的情况。可选表示"那儿有一个值,并且它等于 x "或者"那儿没有值"。
Swfit语言定义后缀?作为命名类型Optional的简写,换句话说,以下两种声明是相等的:
var optionalInteger: Int?
var optionalInteger: Optional<Int>
在这两种情况下,变量 optionalInteger 都是可选整数类型。注意,在类型和 ?之间没有空格。
Optional 是一个含有两种情况的枚举,None 和 Some(T),用来表示可能有或可能没有值。任何类型都可以明确声明为(或者隐式转换)可选类型。当声明一个可选类型的时候,要确保用括号给 ? 操作符一个合适的范围。例如,声明可选整数数组,应该写成 (Int[])? 写成 Int[]? 会报错。
当你声明一个可选变量或者可选属性的时候没有提供初始值,它的值会默认为 nil。
可选项遵照 LogicValue 协议,因此可以出现在布尔环境中。在这种情况下,如果可选类型T?包含类型为T的任何值(也就是说它的值是 Optional.Some(T) ),这个可选类型等于 true,反之为 false。
如果一个可选类型的实例包含一个值,你可以用后缀操作符 !来访问这个值,如下所示:
optionalInteger = 42
optionalInteger! // 42
使用操作符!去获取值为nil的可选变量会有运行时错误。
你可以用可选链接和可选绑定选择性执行可选表达式上的操作。如果值为nil,任何操作都不会执行,也不会有运行报错。
让我们来详细看下以下实例来了解 Swift 中可选类型的应用:
import Cocoavar myString:String? = nilif myString != nil {print(myString)
}else{print("字符串为 nil")
}
以上程序执行结果为:
字符串为 nil
可选类型类似于Objective-C中指针的nil值,但是nil只对类(class)有用,而可选类型对所有的类型都可用,并且更安全。
强制解析
当你确定可选类型确实包含值之后,你可以在可选的名字后面加一个感叹号(!)来获取值。这个感叹号表示"我知道这个可选有值,请使用它。"这被称为可选值的强制解析(forced unwrapping)。
注意:
使用!
来获取一个不存在的可选值会导致运行时错误。使用!
来强制解析值之前,一定要确定可选包含一个非nil
的值。
强制解析可选值,使用感叹号(!):
import Cocoavar myString:String?myString = "Hello, Swift!"if myString != nil {// 强制解析print( myString! )
}else{print("myString 值为 nil")
}
自动解析
你可以在声明可选变量时使用感叹号(!)替换问号(?)。这样可选变量在使用时就不需要再加一个感叹号(!)来获取值,它会自动解析。
import Cocoavar myString:String!myString = "Hello, Swift!"if myString != nil {print(myString)
}else{print("myString 值为 nil")
}
可选绑定
使用可选绑定(optional binding)来判断可选类型是否包含值,如果包含就把值赋给一个临时常量或者变量。可选绑定可以用在if和while语句中来对可选类型的值进行判断并把值赋给一个常量或者变量。
像下面这样在if语句中写一个可选绑定:
if let constantName = someOptional {statements
}
类型标注
当你声明常量或者变量的时候可以加上类型标注(type annotation),说明常量或者变量中要存储的值的类型。如果要添加类型标注,需要在常量或者变量名后面加上一个冒号和空格,然后加上类型名称。
var constantName:<data type> = <optional initial value>事例:
let constB:Float = 3.14159
常量命名
Swift 是一个区分大小写的语言,所以字母大写与小写是不一样的。
常量名也可以使用简单的 Unicode 字符,如下实例:
let 你好 = "你好世界"
print(你好)
以上程序执行结果为:
你好世界
常量输出
变量和常量可以使用 print(swift 2 将 print 替换了 println) 函数来输出。
在字符串中可以使用括号与反斜线来插入常量,如下实例:
let name = "菜鸟教程"
let site = "http://www.runoob.com"print("\(name)的官网地址为:\(site)")
以上程序执行结果为:
菜鸟教程的官网地址为:http://www.runoob.com
整型字面量
整型字面量可以是一个十进制,二进制,八进制或十六进制常量。 二进制前缀为 0b,八进制前缀为 0o,十六进制前缀为 0x,十进制没有前缀:
let binaryInteger = 0b10001 // 17 - 二进制表示
let octalInteger = 0o21 // 17 - 八进制表示
let hexadecimalInteger = 0x11 // 17 - 十六进制表示
浮点型字面量
浮点型字面量有整数部分,小数点,小数部分及指数部分。
除非特别指定,浮点型字面量的默认推导类型为 Swift 标准库类型中的 Double,表示64位浮点数。
浮点型字面量默认用十进制表示(无前缀),也可以用十六进制表示(加前缀 0x)。
十进制浮点型字面量由十进制数字串后跟小数部分或指数部分(或两者皆有)组成。十进制小数部分由小数点 . 后跟十进制数字串组成。指数部分由大写或小写字母 e 为前缀后跟十进制数字串组成,这串数字表示 e 之前的数量乘以 10 的几次方。例如:1.25e2 表示 1.25 ⨉ 10^2,也就是 125.0;同样,1.25e-2 表示 1.25 ⨉ 10^-2,也就是 0.0125。
十六进制浮点型字面量由前缀 0x 后跟可选的十六进制小数部分以及十六进制指数部分组成。十六进制小数部分由小数点后跟十六进制数字串组成。指数部分由大写或小写字母 p 为前缀后跟十进制数字串组成,这串数字表示 p 之前的数量乘以 2 的几次方。例如:0xFp2 表示 15 ⨉ 2^2,也就是 60;同样,0xFp-2 表示 15 ⨉ 2^-2,也就是 3.75。
负的浮点型字面量由一元运算符减号 - 和浮点型字面量组成,例如 -42.5。
符串型字面量
字符串型字面量由被包在双引号中的一串字符组成,形式如下:
"characters"
字符串型字面量中不能包含未转义的双引号 (")、未转义的反斜线(\)、回车符或换行符。
转义字符 | 含义 |
---|---|
\0 | 空字符 |
\\ | 反斜线 \ |
\b | 退格(BS) ,将当前位置移到前一列 |
\f | 换页(FF),将当前位置移到下页开头 |
\n | 换行符 |
\r | 回车符 |
\t | 水平制表符 |
\v | 垂直制表符 |
\' | 单引号 |
\" | 双引号 |
\000 | 1到3位八进制数所代表的任意字符 |
\xhh... | 1到2位十六进制所代表的任意字符 |
布尔型字面量
布尔型字面量的默认类型是 Bool。
布尔值字面量有三个值,它们是 Swift 的保留关键字:
-
true 表示真。
-
false 表示假。
-
nil 表示没有值。
位运算符
位运算符用来对二进制位进行操作,~,&,|,^分别为取反,按位与与,按位与或,按位与异或运算,如下表实例:
p | q | p & q | p | q | p ^ q |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
进行位运算:
运算符 | 描述 | 图解 | 实例 |
---|---|---|---|
& | 按位与。按位与运算符对两个数进行操作,然后返回一个新的数,这个数的每个位都需要两个输入数的同一位都为1时才为1。 | (A & B) 结果为 12, 二进制为 0000 1100 | |
| | 按位或。按位或运算符|比较两个数,然后返回一个新的数,这个数的每一位设置1的条件是两个输入数的同一位都不为0(即任意一个为1,或都为1)。 | (A | B) 结果为 61, 二进制为 0011 1101 | |
^ | 按位异或. 按位异或运算符^比较两个数,然后返回一个数,这个数的每个位设为1的条件是两个输入数的同一位不同,如果相同就设为0。 | (A ^ B) 结果为 49, 二进制为 0011 0001 | |
~ | 按位取反运算符~对一个操作数的每一位都取反。 | (~A ) 结果为 -61, 二进制为 1100 0011 in 2's complement form. | |
<< | 按位左移。左移操作符(<<)将操作数的所有位向左移动指定的位数。 | 下图展示了11111111 << 1(11111111 左移一位)的结果。蓝色数字表示被移动位,灰色表示被丢弃位,空位用橙色的0填充。 | A << 2 结果为 240, 二进制为 1111 0000 |
>> | 按位右移。右移操作符(>>)将操作数的所有位向右移动指定的位数。 | 下图展示了11111111 >> 1(11111111 右移一位)的结果。蓝色数字表示被移动位,灰色表示被丢弃位,空位用橙色的0填充。 | A >> 2 结果为 15, 二进制为 0000 1111 |
Swift 提供了两个区间的运算符。
运算符 | 描述 | 实例 |
---|---|---|
闭区间运算符 | 闭区间运算符(a...b)定义一个包含从a到b(包括a和b)的所有值的区间,b必须大于等于a。 闭区间运算符在迭代一个区间的所有值时是非常有用的,如在for-in循环中: | 1...5 区间值为 1, 2, 3, 4 和 5 |
半开区间运算符 | 半开区间(a..<b)定义一个从a到b但不包括b的区间。 之所以称为半开区间,是因为该区间包含第一个值而不包括最后的值。 | 1..< 5 区间值为 1, 2, 3, 和 4 |
运算符优先级
在一个表达式中可能包含多个有不同运算符连接起来的、具有不同数据类型的数据对象;由于表达式有多种运算,不同的运算顺序可能得出不同结果甚至出现错误运算错误,因为当表达式中含多种运算时,必须按一定顺序进行结合,才能保证运算的合理性和结果的正确性、唯一性。
优先级从上到下依次递减,最上面具有最高的优先级,逗号操作符具有最低的优先级。
相同优先级中,按结合顺序计算。大多数运算是从左至右计算,只有三个优先级是从右至左结合的,它们是单目运算符、条件运算符、赋值运算符。
基本的优先级需要记住:
- 指针最优,单目运算优于双目运算。如正负号。
- 先乘除(模),后加减。
- 先算术运算,后移位运算,最后位运算。请特别注意:1 << 3 + 2 & 7 等价于 (1 << (3 + 2))&7
- 逻辑运算最后计算
Swift 运算符优先级 (从高到低):
运算符 | 实例 |
---|---|
位运算符 | >> &<< &>> >> |
乘法运算符 | &* % & * / |
加法运算符 | | &+ &- + - ^ |
区间运算符 | ..< ... |
类型转换运算符 | is as |
nil 的聚合运算 | ?? |
比较运算符 | != > < >= <= === == |
逻辑与运算符 | && |
逻辑或运算符 | || |
波浪箭头 | ~> |
三元运算符 | ?: |
箭头函数 | ( ) |
赋值运算符 | |= %= /= &<<= &>>= &= *= >>= <<= ^= += -= |
合并空值运算符:??
- 合并空值运算符 a ?? b 如果可选项 a 有值则展开,如果没有值,是 nil,则返回默认值 b。
- 表达式 a 必须是一个可选类型,表达式 b 必须与 a 的存储类型相同
- 合并空值运算符,实际上是三元运算符作用到 Optional 上的缩写 a != nil ? a! : b
- 如果 a 的值是非空,b的值将不会被考虑,也就是合并空值运算符是短路的。
var fff : [String]?
let k=["test"] as? [String] ?? ["str1", "str2", "str3"]
print(k)
let ff=fff as? [String] ?? ["str1", "str2", "str3"]
print(ff)
结果:
["test"]
["str1", "str2", "str3"]
循环类型
Swift 语言提供了以下几种循环类型。点击链接查看每个类型的详细描述:
循环类型 | 描述 |
---|---|
for-in | 遍历一个集合里面的所有元素,例如由数字表示的区间、数组中的元素、字符串中的字符。 |
for 循环 | 该循环方式在 Swift 3 中已经弃用。 用来重复执行一系列语句直到达成特定条件达成,一般通过在每次循环完成后增加计数器的值来实现。 |
while 循环 | 运行一系列语句,如果条件为true,会重复运行,直到条件变为false。 |
repeat...while 循环 | 类似 while 语句区别在于判断循环条件之前,先执行一次循环的代码块。 |
循环控制语句
循环控制语句改变你代码的执行顺序,通过它你可以实现代码的跳转。Swift 以下几种循环控制语句:
控制语句 | 描述 |
---|---|
continue 语句 | 告诉一个循环体立刻停止本次循环迭代,重新开始下次循环迭代。 |
break 语句 | 中断当前循环。 |
fallthrough 语句 | 如果在一个case执行完后,继续执行下面的case,需要使用fallthrough(贯穿)关键字。 |
创建字符串
你可以通过使用字符串字面量或 String 类的实例来创建一个字符串:
// 使用字符串字面量
var stringA = "Hello, World!"// String 实例化
var stringB = String("Hello, World!")
空字符串
你可以使用空的字符串字面量赋值给变量或初始化一个String类的实例来初始值一个空的字符串。 我们可以使用字符串属性 isEmpty 来判断字符串是否为空:
// 使用字符串字面量创建空字符串
var stringA = ""if stringA.isEmpty {print( "stringA 是空的" )
} else {print( "stringA 不是空的" )
}// 实例化 String 类来创建空字符串
let stringB = String()
字符串常量
你可以将一个字符串赋值给一个变量或常量,变量是可修改的,常量是不可修改的。
// stringA 可被修改
var stringA = "菜鸟教程:"
stringA += "http://www.runoob.com"
print( stringA )
输出结果:
菜鸟教程:http://www.runoob.com
字符串中插入值
字符串插值是一种构建新字符串的方式,可以在其中包含常量、变量、字面量和表达式。 您插入的字符串字面量的每一项都在以反斜线为前缀的圆括号中:
var varA = 20
let constA = 100
var varC:Float = 20.0var stringA = "\(varA) 乘于 \(constA) 等于 \(varC * 100)"
print( stringA )
以上程序执行输出结果为:
20 乘于 100 等于 2000.0
字符串连接
字符串可以通过 + 号来连接,实例如下:
let constA = "菜鸟教程:"
let constB = "http://www.runoob.com"var stringA = constA + constBprint( stringA )
以上程序执行输出结果为:
菜鸟教程:http://www.runoob.com
字符串长度
字符串长度使用 String.count 属性来计算,实例如下:
Swift 3 版本使用的是 String.characters.count
import Cocoavar varA = "www.runoob.com"print( "\(varA), 长度为 \(varA.count)" )
以上程序执行输出结果为:
www.runoob.com, 长度为 14
字符串比较
你可以使用 == 来比较两个字符串是否相等:
var varA = "Hello, Swift!"
var varB = "Hello, World!"if varA == varB {print( "\(varA) 与 \(varB) 是相等的" )
} else {print( "\(varA) 与 \(varB) 是不相等的" )
}
以上程序执行输出结果为:
Hello, Swift! 与 Hello, World! 是不相等的
Unicode 字符串
Unicode 是一个国际标准,用于文本的编码,Swift 的 String 类型是基于 Unicode建立的。你可以循环迭代出字符串中 UTF-8 与 UTF-16 的编码,实例如下:
import Cocoavar unicodeString = "菜鸟教程"print("UTF-8 编码: ")
for code in unicodeString.utf8 {print("\(code) ")
}print("\n")print("UTF-16 编码: ")
for code in unicodeString.utf16 {print("\(code) ")
}
以上程序执行输出结果为:
UTF-8 编码:
232
143
156
233
184
159
230
149
153
231
168
139
UTF-16 编码:
33756
40479
25945
31243
字符串函数及运算符
Swift 支持以下几种字符串函数及运算符:
序号 | 函数/运算符 & 描述 |
---|---|
1 | isEmpty 判断字符串是否为空,返回布尔值 |
2 | hasPrefix(prefix: String) 检查字符串是否拥有特定前缀 |
3 | hasSuffix(suffix: String) 检查字符串是否拥有特定后缀。 |
4 | Int(String) 转换字符串数字为整型。 实例: let myString: String = "256" let myInt: Int? = Int(myString) |
5 | String.count Swift 3 版本使用的是 String.characters.count 计算字符串的长度 |
6 | utf8 您可以通过遍历 String 的 utf8 属性来访问它的 UTF-8 编码 |
7 | utf16 您可以通过遍历 String 的 utf8 属性来访问它的 utf16 编码 |
8 | unicodeScalars 您可以通过遍历String值的unicodeScalars属性来访问它的 Unicode 标量编码. |
9 | + 连接两个字符串,并返回一个新的字符串 |
10 | += 连接操作符两边的字符串并将新字符串赋值给左边的操作符变量 |
11 | == 判断两个字符串是否相等 |
12 | < 比较两个字符串,对两个字符串的字母逐一比较。 |
13 | != 比较两个字符串是否不相等。 |
字符串分割数组 -- 基于空格
let fullName = "First Last" let fullNameArr = fullName.characters.split{$0 == " "}.map(String.init) // or simply: // let fullNameArr = fullName.characters.split{" "}.map(String.init)//现在的方法 var fullNameArr = fullName.split(separator: " ")fullNameArr[0] // First fullNameArr[1] // Last
字符串的遍历 Swift 5:
let str = "菜鸟教程runoob.com"print("---- 正序遍历 ----") var i = 0 for ch in str {print("\(i): \(ch)")i += 1 }print("---- 逆序遍历 ----") var j = str.count for ch in str.reversed() {j -= 1print("\(j): \(ch)") }print("---- 基于索引的正序遍历 ----") for i in 0..<str.count {let ch: Character = str[str.index(str.startIndex, offsetBy: i)]print("\(i): \(ch)") }print("---- 基于索引的逆序遍历 ----") //for i in stride(from: str.count - 1, to: -1, by: -1) { for i in stride(from: str.count - 1, through: 0, by: -1) {let ch: Character = str[str.index(str.startIndex, offsetBy: i)]print("\(i): \(ch)") }print("---- 基于EnumeratedSequence的遍历 ----") for (i, ch) in str.enumerated() {print("\(i): \(ch)") }
字符串连接字符
以下实例演示了使用 String 的 append() 方法来实现字符串连接字符:
import Cocoavar varA:String = "Hello " let varB:Character = "G"varA2.append(" \(varB) " )print("varC = \(varA)")
以上程序执行输出结果为:
varC = Hello G
修改数组
你可以使用 append() 方法或者赋值运算符 += 在数组末尾添加元素,如下所示,我们初始化一个数组,并向其添加元素:
import Cocoavar someInts = [Int]()someInts.append(20)
someInts.append(30)
someInts += [40]var someVar = someInts[0]print( "第一个元素的值 \(someVar)" )
print( "第二个元素的值 \(someInts[1])" )
print( "第三个元素的值 \(someInts[2])" )
以上程序执行输出结果为:
第一个元素的值 20
第二个元素的值 30
第三个元素的值 40
我们也可以通过索引修改数组元素的值:
import Cocoavar someInts = [Int]()someInts.append(20)
someInts.append(30)
someInts += [40]// 修改最后一个元素
someInts[2] = 50
如果我们同时需要每个数据项的值和索引值,可以使用 String 的 enumerate() 方法来进行数组遍历。实例如下:
import Cocoavar someStrs = [String]()someStrs.append("Apple")
someStrs.append("Amazon")
someStrs.append("Runoob")
someStrs += ["Google"]for (index, item) in someStrs.enumerated() {print("在 index = \(index) 位置上的值为 \(item)")
}
合并数组
我们可以使用加法操作符(+)来合并两种已存在的相同类型数组。新数组的数据类型会从两个数组的数据类型中推断出来:
count 属性
我们可以使用 count 属性来计算数组元素个数:
isEmpty 属性
我们可以通过只读属性 isEmpty 来判断数组是否为空,返回布尔值:
创建数组的方法不推荐使用文章中记载的方法。
推荐:
var names: [String] = []
var lookup: [String: Int] = [:]
不推荐:
var names = [String]()
var lookup = [String: Int]()
创建字典
我们可以使用以下语法来创建一个特定类型的空字典:
var someDict = [KeyType: ValueType]()
以下是创建一个空字典,键的类型为 Int,值的类型为 String 的简单语法:
var someDict = [Int: String]()
以下为创建一个字典的实例:
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
访问字典
我们可以根据字典的索引来访问数组的元素,语法如下:
var someVar = someDict[key]
修改字典
我们可以使用 updateValue(forKey:) 增加或更新字典的内容。如果 key 不存在,则添加值,如果存在则修改 key 对应的值。updateValue(_:forKey:)方法返回Optional值。实例如下:
import Cocoavar someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]var oldVal = someDict.updateValue("One 新的值", forKey: 1)var someVar = someDict[1]print( "key = 1 旧的值 \(oldVal)" ) print( "key = 1 的值为 \(someVar)" ) print( "key = 2 的值为 \(someDict[2])" ) print( "key = 3 的值为 \(someDict[3])" )
以上程序执行输出结果为:
key = 1 旧的值 Optional("One") key = 1 的值为 Optional("One 新的值") key = 2 的值为 Optional("Two") key = 3 的值为 Optional("Three")
移除 Key-Value 对
我们可以使用 removeValueForKey() 方法来移除字典 key-value 对。如果 key 存在该方法返回移除的值,如果不存在返回 nil 。实例如下:
import Cocoavar someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]var removedValue = someDict.removeValue(forKey: 2)print( "key = 1 的值为 \(someDict[1])" )
print( "key = 2 的值为 \(someDict[2])" )
print( "key = 3 的值为 \(someDict[3])" )
以上程序执行输出结果为:
key = 1 的值为 Optional("One")
key = 2 的值为 nil
key = 3 的值为 Optional("Three")
你也可以通过指定键的值为 nil 来移除 key-value(键-值)对。实例如下:
someDict[2] = nil
print( "key = 2 的值为 \(someDict[2])" )
key = 2 的值为 nil
遍历字典
我们可以使用 for-in 循环来遍历某个字典中的键值对。实例如下:
import Cocoavar someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]for (key, value) in someDict {print("字典 key \(key) - 字典 value \(value)")
}
字典转换为数组
你可以提取字典的键值(key-value)对,并转换为独立的数组。实例如下:
import Cocoavar someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]let dictKeys = [Int](someDict.keys) let dictValues = [String](someDict.values)
print("输出字典的键(key)")for (key) in dictKeys {print("\(key)") }print("输出字典的值(value)")for (value) in dictValues {print("\(value)") }
以上程序执行输出结果为:
输出字典的键(key) 2 3 1 输出字典的值(value) Two Three One
count 属性
我们可以使用只读的 count 属性来计算字典有多少个键值对:
isEmpty 属性
Y我们可以通过只读属性 isEmpty 来判断字典是否为空,返回布尔值:
函数定义
Swift 定义函数使用关键字 func。
定义函数的时候,可以指定一个或多个输入参数和一个返回值类型。
每个函数都有一个函数名来描述它的功能。通过函数名以及对应类型的参数值来调用这个函数。函数的参数传递的顺序必须与参数列表相同。
函数的实参传递的顺序必须与形参列表相同,-> 后定义函数的返回值类型。
语法
func funcname(形参) -> returntype
{Statement1Statement2……Statement Nreturn parameters
}
实例
以下我们定义了一个函数名为 runoob 的函数,形参的数据类型为 String,返回值也为 String:
import Cocoafunc runoob(site: String) -> String {return (site)
}
print(runoob(site: "www.runoob.com"))
以上程序执行输出结果为:
www.runoob.com
函数参数
函数可以接受一个或者多个参数,这些参数被包含在函数的括号之中,以逗号分隔。
以下实例向函数 runoob 传递站点名 name 和站点地址 site:
import Cocoafunc runoob(name: String, site: String) -> String {return name + site
}
print(runoob(name: "菜鸟教程:", site: "www.runoob.com"))
print(runoob(name: "Google:", site: "www.google.com"))
以上程序执行输出结果为:
菜鸟教程:www.runoob.com
Google:www.google.com
不带参数函数
我们可以创建不带参数的函数。
语法:
func funcname() -> datatype {return datatype
}
元组作为函数返回值
函数返回值类型可以是字符串,整型,浮点型等。
元组与数组类似,不同的是,元组中的元素可以是任意类型,使用的是圆括号。
你可以用元组(tuple)类型让多个值作为一个复合值从函数中返回。
下面的这个例子中,定义了一个名为minMax(_:)的函数,作用是在一个Int数组中找出最小值与最大值。
import Cocoafunc minMax(array: [Int]) -> (min: Int, max: Int) {var currentMin = array[0]var currentMax = array[0]for value in array[1..<array.count] {if value < currentMin {currentMin = value} else if value > currentMax {currentMax = value}}return (currentMin, currentMax)
}let bounds = minMax(array: [8, -6, 2, 109, 3, 71])
print("最小值为 \(bounds.min) ,最大值为 \(bounds.max)")
minMax(_:)函数返回一个包含两个Int值的元组,这些值被标记为min和max,以便查询函数的返回值时可以通过名字访问它们。
以上程序执行输出结果为:
最小值为 -6 ,最大值为 109
如果你不确定返回的元组一定不为nil,那么你可以返回一个可选的元组类型。
你可以通过在元组类型的右括号后放置一个问号来定义一个可选元组,例如(Int, Int)?或(String, Int, Bool)?
注意
可选元组类型如(Int, Int)?
与元组包含可选类型如(Int?, Int?)
是不同的.可选的元组类型,整个元组是可选的,而不只是元组中的每个元素值。
前面的minMax(_:)
函数返回了一个包含两个Int
值的元组。但是函数不会对传入的数组执行任何安全检查,如果array
参数是一个空数组,如上定义的minMax(_:)
在试图访问array[0]
时会触发一个运行时错误。
为了安全地处理这个"空数组"问题,将minMax(_:)
函数改写为使用可选元组返回类型,并且当数组为空时返回nil
:
import Cocoafunc minMax(array: [Int]) -> (min: Int, max: Int)? {if array.isEmpty { return nil }var currentMin = array[0]var currentMax = array[0]for value in array[1..<array.count] {if value < currentMin {currentMin = value} else if value > currentMax {currentMax = value}}return (currentMin, currentMax)
}
if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) {print("最小值为 \(bounds.min),最大值为 \(bounds.max)")
}
以上程序执行输出结果为:
最小值为 -6,最大值为 109
没有返回值函数
下面是 runoob(_:) 函数的另一个版本,这个函数接收菜鸟教程官网网址参数,没有指定返回值类型,并直接输出 String 值,而不是返回它:
import Cocoafunc runoob(site: String) {print("菜鸟教程官网:\(site)")
}
runoob(site: "http://www.runoob.com")
以上程序执行输出结果为:
菜鸟教程官网:http://www.runoob.com
函数参数名称
函数参数都有一个外部参数名和一个局部参数名。
局部参数名
局部参数名在函数的实现内部使用。
func sample(number: Int) {println(number)
}
以上实例中 number 为局部参数名,只能在函数体内使用。
外部参数名
你可以在局部参数名前指定外部参数名,中间以空格分隔,外部参数名用于在函数调用时传递给函数的参数。
如下你可以定义以下两个函数参数名并调用它:
import Cocoafunc pow(firstArg a: Int, secondArg b: Int) -> Int {var res = afor _ in 1..<b {res = res * a}print(res)return res } pow(firstArg:5, secondArg:3)
以上程序执行输出结果为:
125
可变参数
可变参数可以接受零个或多个值。函数调用时,你可以用可变参数来指定函数参数,其数量是不确定的。
可变参数通过在变量类型名后面加入(...)的方式来定义。
import Cocoafunc vari<N>(members: N...){for i in members {print(i)} } vari(members: 4,3,5) vari(members: 4.5, 3.1, 5.6) vari(members: "Google", "Baidu", "Runoob")
以上程序执行输出结果为:
4
3
5
4.5
3.1
5.6
Google
Baidu
Runoob
常量,变量及 I/O 参数
一般默认在函数中定义的参数都是常量参数,也就是这个参数你只可以查询使用,不能改变它的值。
如果想要声明一个变量参数,可以在参数定义前加 inout 关键字,这样就可以改变这个参数的值了。
例如:
func getName(_ name: inout String).........
此时这个 name 值可以在函数中改变。
一般默认的参数传递都是传值调用的,而不是传引用。所以传入的参数在函数内改变,并不影响原来的那个参数。传入的只是这个参数的副本。
当传入的参数作为输入输出参数时,需要在参数名前加 & 符,表示这个值可以被函数修改。
使用函数类型
在 Swift 中,使用函数类型就像使用其他类型一样。例如,你可以定义一个类型为函数的常量或变量,并将适当的函数赋值给它:
var addition: (Int, Int) -> Int = sum
函数嵌套
函数嵌套指的是函数内定义一个新的函数,外部的函数可以调用函数内定义的函数。
实例如下:
import Cocoafunc calcDecrement(forDecrement total: Int) -> () -> Int {var overallDecrement = 0func decrementer() -> Int {overallDecrement -= totalreturn overallDecrement}return decrementer
}
let decrem = calcDecrement(forDecrement: 30)
print(decrem())
以上程序执行输出结果为:
-30
Swift 闭包
闭包(Closures)是自包含的功能代码块,可以在代码中使用或者用来作为参数传值。
Swift 中的闭包与 C 和 Objective-C 中的代码块(blocks)以及其他一些编程语言中的 匿名函数比较相似。
全局函数和嵌套函数其实就是特殊的闭包。
闭包的形式有:
全局函数 | 嵌套函数 | 闭包表达式 |
有名字但不能捕获任何值。 | 有名字,也能捕获封闭函数内的值。 | 无名闭包,使用轻量级语法,可以根据上下文环境捕获值。 |
Swift中的闭包有很多优化的地方:
语法
以下定义了一个接收参数并返回指定类型的闭包语法:
{(parameters) -> return type instatements }
- 根据上下文推断参数和返回值类型
- 从单行表达式闭包中隐式返回(也就是闭包体只有一行代码,可以省略return)
- 可以使用简化参数名,如$0, $1(从0开始,表示第i个参数...)
- 提供了尾随闭包语法(Trailing closure syntax)
以下闭包形式接收两个参数并返回布尔值:
{(Int, Int) -> Bool inStatement1Statement 2---Statement n
}
实例
import Cocoalet divide = {(val1: Int, val2: Int) -> Int in return val1 / val2
}
let result = divide(200, 20)
print (result)
以上程序执行输出结果为:
10
闭包表达式
闭包表达式是一种利用简洁语法构建内联闭包的方式。 闭包表达式提供了一些语法优化,使得撰写闭包变得简单明了。
sorted 方法
Swift 标准库提供了名为 sorted(by:) 的方法,会根据您提供的用于排序的闭包函数将已知类型数组中的值进行排序。
排序完成后,sorted(by:) 方法会返回一个与原数组大小相同,包含同类型元素且元素已正确排序的新数组。原数组不会被 sorted(by:) 方法修改。
sorted(by:)方法需要传入两个参数:
实例
import Cocoalet names = ["AT", "AE", "D", "S", "BE"]// 使用普通函数(或内嵌函数)提供排序功能,闭包函数类型需为(String, String) -> Bool。
func backwards(s1: String, s2: String) -> Bool {return s1 > s2
}
var reversed = names.sorted(by: backwards)print(reversed)
以上程序执行输出结果为:
["S", "D", "BE", "AT", "AE"]
如果第一个字符串 (s1) 大于第二个字符串 (s2),backwards函数返回true,表示在新的数组中s1应该出现在s2前。 对于字符串中的字符来说,"大于" 表示 "按照字母顺序较晚出现"。 这意味着字母"B"大于字母"A",字符串"S"大于字符串"D"。 其将进行字母逆序排序,"AT"将会排在"AE"之前。
参数名称缩写
Swift 自动为内联函数提供了参数名称缩写功能,您可以直接通过$0,$1,$2来顺序调用闭包的参数。
实例
import Cocoalet names = ["AT", "AE", "D", "S", "BE"]var reversed = names.sorted( by: { $0 > $1 } )
print(reversed)
$0和$1表示闭包中第一个和第二个String类型的参数。
以上程序执行输出结果为:
["S", "D", "BE", "AT", "AE"]
如果你在闭包表达式中使用参数名称缩写, 您可以在闭包参数列表中省略对其定义, 并且对应参数名称缩写的类型会通过函数类型进行推断。in 关键字同样也可以被省略.
运算符函数
实际上还有一种更简短的方式来撰写上面例子中的闭包表达式。
Swift 的String
类型定义了关于大于号 (>
) 的字符串实现,其作为一个函数接受两个String
类型的参数并返回Bool
类型的值。 而这正好与sort(_:)
方法的第二个参数需要的函数类型相符合。 因此,您可以简单地传递一个大于号,Swift可以自动推断出您想使用大于号的字符串函数实现:
import Cocoalet names = ["AT", "AE", "D", "S", "BE"]var reversed = names.sorted(by: >)
print(reversed)
以上程序执行输出结果为:
["S", "D", "BE", "AT", "AE"]
以上三种方法方法实现相同:
func backwards(s1: String, s2: String) -> Bool {return s1 > s2
}
var reversed = names.sorted(by: backwards)
尾随闭包
尾随闭包是一个书写在函数括号之后的闭包表达式,函数支持将其作为最后一个参数调用。
func someFunctionThatTakesAClosure(closure: () -> Void) {// 函数体部分
}// 以下是不使用尾随闭包进行函数调用
someFunctionThatTakesAClosure({// 闭包主体部分
})// 以下是使用尾随闭包进行函数调用
someFunctionThatTakesAClosure() {// 闭包主体部分
}
实例
import Cocoalet names = ["AT", "AE", "D", "S", "BE"]//尾随闭包 var reversed = names.sorted() { $0 > $1 } print(reversed)
sort() 后的 { $0 > $1} 为尾随闭包。
以上程序执行输出结果为:
["S", "D", "BE", "AT", "AE"]
注意: 如果函数只需要闭包表达式一个参数,当您使用尾随闭包时,您甚至可以把
()
省略掉。reversed = names.sorted { $0 > $1 }
捕获值
闭包可以在其定义的上下文中捕获常量或变量。
即使定义这些常量和变量的原域已经不存在,闭包仍然可以在闭包函数体内引用和修改这些值。
Swift最简单的闭包形式是嵌套函数,也就是定义在其他函数的函数体内的函数。
嵌套函数可以捕获其外部函数所有的参数以及定义的常量和变量。
闭包是引用类型
上面的例子中,incrementByTen是常量,但是这些常量指向的闭包仍然可以增加其捕获的变量值。
这是因为函数和闭包都是引用类型。
无论您将函数/闭包赋值给一个常量还是变量,您实际上都是将常量/变量的值设置为对应函数/闭包的引用。 上面的例子中,incrementByTen指向闭包的引用是一个常量,而并非闭包内容本身。
这也意味着如果您将闭包赋值给了两个不同的常量/变量,两个值都会指向同一个闭包:
-
Swift 中使用 enum 关键词来创建枚举并且把它们的整个定义放在一对大括号内:
enum enumname {// 枚举定义放在这里
}
举中定义的值(如 Sunday
,Monday
,……
和Saturday
)是这个枚举的成员值(或成员)。case
关键词表示一行新的成员值将被定义。
注意: 和 C 和 Objective-C 不同,Swift 的枚举成员在被创建时不会被赋予一个默认的整型值。在上面的
DaysofaWeek
例子中,Sunday
,Monday
,……
和Saturday
不会隐式地赋值为0
,1
,……
和6
。相反,这些枚举成员本身就有完备的值,这些值是已经明确定义好的DaysofaWeek
类型。
var weekDay = DaysofaWeek.THURSDAY
weekDay
的类型可以在它被DaysofaWeek
的一个可能值初始化时推断出来。一旦weekDay
被声明为一个DaysofaWeek
,你可以使用一个缩写语法(.)将其设置为另一个DaysofaWeek
的值:
var weekDay = .THURSDAY
当weekDay
的类型已知时,再次为其赋值可以省略枚举名。使用显式类型的枚举值可以让代码具有更好的可读性。
枚举可分为相关值与原始值。
相关值与原始值的区别
相关值 | 原始值 |
---|---|
不同数据类型 | 相同数据类型 |
实例: enum {10,0.8,"Hello"} | 实例: enum {10,35,50} |
值的创建基于常量或变量 | 预先填充的值 |
相关值是当你在创建一个基于枚举成员的新常量或变量时才会被设置,并且每次当你这么做得时候,它的值可以是不同的。 | 原始值始终是相同的 |
相关值
以下实例中我们定义一个名为 Student 的枚举类型,它可以是 Name 的一个字符串(String),或者是 Mark 的一个相关值(Int,Int,Int)。
import Cocoaenum Student{case Name(String)case Mark(Int,Int,Int) } var studDetails = Student.Name("Runoob") var studMarks = Student.Mark(98,97,95) switch studMarks { case .Name(let studName):print("学生的名字是: \(studName)。") case .Mark(let Mark1, let Mark2, let Mark3):print("学生的成绩是: \(Mark1),\(Mark2),\(Mark3)。") }
以上程序执行输出结果为:
学生的成绩是: 98,97,95。
原始值
原始值可以是字符串,字符,或者任何整型值或浮点型值。每个原始值在它的枚举声明中必须是唯一的。
在原始值为整数的枚举时,不需要显式的为每一个成员赋值,Swift会自动为你赋值。
例如,当使用整数作为原始值时,隐式赋值的值依次递增1。如果第一个值没有被赋初值,将会被自动置为0。
import Cocoaenum Month: Int {case January = 1, February, March, April, May, June, July, August, September, October, November, December }let yearMonth = Month.May.rawValue print("数字月份为: \(yearMonth)。")
以上程序执行输出结果为:
数字月份为: 5。
Swift 结构体是构建代码所用的一种通用且灵活的构造体。
我们可以为结构体定义属性(常量、变量)和添加方法,从而扩展结构体的功能。
与 C 和 Objective C 不同的是:
-
结构体不需要包含实现文件和接口。
-
结构体允许我们创建一个单一文件,且系统会自动生成面向其它代码的外部接口。
结构体总是通过被复制的方式在代码中传递,因此它的值是不可修改的。
语法
我们通过关键字 struct 来定义结构体:
struct nameStruct { Definition 1Definition 2……Definition N
}
实例
我们定义一个名为 MarkStruct 的结构体 ,结构体的属性为学生三个科目的分数,数据类型为 Int:
struct MarkStruct{var mark1: Intvar mark2: Intvar mark3: Int }
我们可以通过结构体名来访问结构体成员。
通过 . 号来访问结构体成员的值。
结构体应用
在你的代码中,你可以使用结构体来定义你的自定义数据类型。
结构体实例总是通过值传递来定义你的自定义数据类型。
按照通用的准则,当符合一条或多条以下条件时,请考虑构建结构体:
- 结构体的主要目的是用来封装少量相关简单数据值。
- 有理由预计一个结构体实例在赋值或传递时,封装的数据将会被拷贝而不是被引用。
- 任何在结构体中储存的值类型属性,也将会被拷贝,而不是被引用。
- 结构体不需要去继承另一个已存在类型的属性或者行为。
举例来说,以下情境中适合使用结构体:
- 几何形状的大小,封装一个
width
属性和height
属性,两者均为Double
类型。 - 一定范围内的路径,封装一个
start
属性和length
属性,两者均为Int
类型。 - 三维坐标系内一点,封装
x
,y
和z
属性,三者均为Double
类型。
结构体实例是通过值传递而不是通过引用传递。
Swift 类是构建代码所用的一种通用且灵活的构造体。
我们可以为类定义属性(常量、变量)和方法。
与其他编程语言所不同的是,Swift 并不要求你为自定义类去创建独立的接口和实现文件。你所要做的是在一个单一文件中定义一个类,系统会自动生成面向其它代码的外部接口。
相关文章:
Swift学习内容精选(一)
Swift 可选(Optionals)类型 Swift 的可选(Optional)类型,用于处理值缺失的情况。可选表示"那儿有一个值,并且它等于 x "或者"那儿没有值"。 Swfit语言定义后缀?作为命名类型Optional的简写&…...
Marin说PCB之封装设计系列---(02)--异形焊盘的封装设计总结
每天下班回家看电视本来是一件很美好的事情,可是正当我磕着瓜子看着异人之下的时候,手机突然响起来了,我以为是我们组哪个同事找我呢。一接电话居然是我的老朋友陈世美陈总,江湖人称少妇杀手。给我打电话主要是说他最近遇到一个异…...
SpringBoot使用AOP详解
目录 1 AOP是什么2 AOP概念3 Springboot中使用AOP4 AOP原理5 应用场景 1 AOP是什么 AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续&…...
【Qt】QGroundControl入门1:介绍
1、简介 1.1 QGroundControl QGroundControl是一款开源的无人机地面控制站软件,依赖Qt库,简称QGC。 QGroundControl为任何支持 MAVLink协议 的无人机提供完整的飞行控制和任务规划。QGroundControl为 PX4 和 ArduPilot 驱动的无人机提供驱动配置。 源码:https://github.co…...
第36章_瑞萨MCU零基础入门系列教程之步进电机控制实验
本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写,需要的同学可以在这里获取: https://item.taobao.com/item.htm?id728461040949 配套资料获取:https://renesas-docs.100ask.net 瑞萨MCU零基础入门系列教程汇总: ht…...
198.打家劫舍,213.打家劫舍II,337.打家劫舍III
代码随想录训练营第48天|198.打家劫舍,213.打家劫舍II,337.打家劫舍III 198.打家劫舍文章思路代码 213.打家劫舍III文章思路代码 337.打家劫舍III文章思路代码 总结 198.打家劫舍 文章 代码随想录|0198.打家劫舍 思路 d p [ i ] M a x ( d p [ i − …...
msvcp140.dll是什么东西,如何解决msvcp140.dll丢失的问题的方法分享
在现代生活中,电脑已经成为我们工作、学习和娱乐的重要工具。然而,电脑问题的出现往往会给我们的生活带来不便。其中,"msvcp140.dll丢失"是一个常见的电脑问题。本文将详细介绍这个问题的原因和解决方法,帮助大家更好地…...
音视频 SDL vs2017配置
一、首先我把SDL放在了C盘根目录下 二、新建空项目 三、添加main.cpp //main.cpp #include<iostream> #include <SDL.h>int main(int argc, char* argv[]) // main函数头必须这样写,因为SDL把main定义成了宏 {SDL_Delay(3000); // 让窗口在屏幕上保持…...
前端面试要点
0914 JScript深拷贝和浅拷贝(js解构赋值算哪个?) 深拷贝和浅拷贝 回流和重绘 回流和重绘 webpack打包流程 Webpack打包 虚拟DOM 虚拟DOM git合并分支 git合并分支 CSS盒子模型 CSS盒子模型 0911 WebPack分包 webpack分包 ts泛型 ts泛型 优化…...
shell字符串处理之字符串比较
引言 我们在使用shell编写脚本时,经常需要对字符串进行处理,如字符串大小比较、模式匹配、替换、截断等。本文将梳理字符串比较中常见的用法。 字符串比较 1. 直接比较字符串 a$1 b$2 c"" # 等于 if [ $a "abc" ];thenecho $a …...
怎么获取别人店铺的商品呢?
jd.item_search_shop(获得店铺的所有商品) 为了进行电商平台 的API开发,首先我们需要做下面几件事情。 1)开发者注册一个账号 2)然后为每个JD应用注册一个应用程序键(App Key) 。 3)下载JDAPI的SDK并掌握基本的API…...
【数据结构】二叉树的链式结构
【数据结构】二叉树的链式存储结构 二叉树的存储结构 typedef int BTDataType; // 二叉树的结构 typedef struct BinaryTreeNode {BTDataType data; // 树的值struct BinaryTreeNode *left; // 左孩子struct BinaryTreeNode *right;// 右孩子 } BinaryTreeNode;二…...
模拟实现C语言--strlen函数
模拟实现C语言–strlen函数 模拟实现C语言--strlen函数一、strlen函数是什么?二、strlen函数的模拟实现2.1 计数器方式实现strlen函数2.2 不创建临时变量计数器方式实现strlen函数2.3 指针-指针方式实现strlen函数 三、strlen函数的返回类型 一、strlen函数是什么&a…...
Spring Boot + Vue的网上商城之物流系统实现
Spring Boot Vue的网上商城之物流系统实现 思路 当构建一个物流系统时,我们可以按照以下步骤进行: 设计数据模型:首先确定系统中需要存储的数据,例如物流公司信息、物流订单信息等。根据需求设计相应的数据模型,包括…...
释放数据价值这道难题,Smartbi V11有解
《未来简史》预言:数据将成为人们未来的信仰。 未来已来,将至已至。如今,数据所扮演的角色与作用超乎想象。从政府将数据要素列入生产要素之中,到数据驱动型业务场景涌现,企业与组织对于数据及其价值的认可度明显提升…...
Day_14 > 指针进阶(3)> bubble函数
目录 1.回顾回调函数 2.写一个bubble_sort函数 2.1认识一下qsort函数 编辑2.2写bubble_sort函数 今天我们继续深入学习指针 1.回顾回调函数 我们回顾一下之前学过的回调函数 回调函数就是一个通过函数指针调用的函数 如果你把函数的指针(地址)…...
sql中怎么查books表下面的内容
要查询 books 表中的所有内容,你可以使用以下 SQL 语句: USE bookmanagement; -- 选择数据库 SELECT * FROM books; -- 查询books表中的所有内容如果你使用的是命令行界面 (mysql 客户端) 来操作数据库,可以直接在命令提示符中输入上述命令…...
Vulnhub系列靶机---HarryPotter-Aragog-1.0.2哈利波特系列靶机-1
文章目录 方式一信息收集主机发现端口扫描目录扫描wpscan工具 漏洞利用msf工具数据库权限用户权限root提权 方式二信息收集gobuster扫描wpscan扫描 漏洞利用POC 靶机文档:HarryPotter: Aragog (1.0.2) 下载地址:Download (Mirror) 方式一 信息收集 主机…...
.NET 8发布首个RC,比.NET 7的超级快更快
.NET 8 发布了首个 RC。据称 RC 阶段会发布两个版本,正式版将于 2023 年 11 月 14 日至 16 日在 .NET Conf 2023 上推出。.NET 8 是长期支持 (LTS) 版本,将会获得 3 年技术支持。 公告写道,此版本为 Android 和 WASM 引入了全新的 AOT 模式、…...
在 Substance Painter中自定义Shader
为什么要学习在Substance Painter中自定义Shader? 答:需要实现引擎与Substance Painter中的渲染效果一致,材质的配置也一致,所见即所得。 基础概述 首先在着色器设置这里,我们可以查看当前渲染使用的着色器 如果没有…...
【自学开发之旅】Flask-restful-Jinjia页面编写template-回顾(五)
restful是web编程里重要的概念 – 一种接口规范也是一种接口设计风格 设计接口: 要考虑:数据返回、接收数据的方式、url、方法 统一风格 rest–表现层状态转移 web–每一类数据–资源 资源通过http的动作来实现状态转移 GET、PUT、POST、DELETE path…...
input 的 placeholder 样式
::placeholder 伪元素 这个伪元素可以改变 input、textarea 占位文本的样式。 input::placeholder {color: green; }完整的兼容性写法: input {&::-webkit-input-placeholder, /* WebKit browsers*/ &:-moz-input-placeholder, /* Mozilla Firefox 4 to …...
4.4-Spring源码循环依赖终极讲解
回顾上期内容 new 容器 new AnnotateBeanDefinitionReader 的时候创建很多创世纪的类,其中有一个ConfigurationPostProcessor是用来解析配置类的,将其注册起来存到Bean定义的Map中【这个类是基于Bean工厂后置处理器的】 这一步是将配置类注册到Bean定…...
腾讯云4核8G服务器选CVM还是轻量比较好?价格对比
腾讯云4核8G云服务器可以选择轻量应用服务器或CVM云服务器标准型S5实例,轻量4核8G12M服务器446元一年,CVM S5云服务器935元一年,相对于云服务器CVM,轻量应用服务器性价比更高,轻量服务器CPU和CVM有区别吗?性…...
数学实验-素数(Mathematica实现)
一、实验名称:素数 二、实验环境:Mathematica 10.3软件 三、实验目的:本实验将探讨素数的规律,研究素数的判别、最大的素数、构成生成素数的公式和素数的分布,并学会求解某些范围内的素数。 四、实验内容、步骤以及…...
Vue3样式绑定
文章目录 Vue3样式绑定1. class 属性绑定1.1 v-bind:class 设置一个对象,从而动态的切换 class1.2 在对象中传入更多属性用来动态切换多个 class1.3 直接绑定数据里的一个对象1.4 绑定一个返回对象的计算属性。这是一个常用且强大的模式1. 5 数据语法1.6 errorClass…...
【深度学习】 Python 和 NumPy 系列教程(廿二):Matplotlib详解:2、3d绘图类型(8)3D饼图(3D Pie Chart)
一、前言 Python是一种高级编程语言,由Guido van Rossum于1991年创建。它以简洁、易读的语法而闻名,并且具有强大的功能和广泛的应用领域。Python具有丰富的标准库和第三方库,可以用于开发各种类型的应用程序,包括Web开发、数据分…...
数仓主题域和数据域、雪花模型,星型模型和星座模型
数仓模型和领域划分 一、主题域和数据域的差别二、雪花模型,星座模型和星型模型 一、主题域和数据域的差别 明确数据域作为数仓搭建的重要一环,能够让数仓的数据便于管理和应用。 数据域和主题域都是数据仓库中的重要概念,但含义略有不同&am…...
黑马头条 热点文章实时计算、kafkaStream
热点文章-实时计算 1 今日内容 1.1 定时计算与实时计算 1.2 今日内容 kafkaStream 什么是流式计算kafkaStream概述kafkaStream入门案例Springboot集成kafkaStream 实时计算 用户行为发送消息kafkaStream聚合处理消息更新文章行为数量替换热点文章数据 2 实时流式计算 2…...
数据分析:利用gpt进行归因分析
prompt: 你是某电商平台的一名数据分析师,发现昨日的GMV环比下降了5%,请对这数据变动做出归因。 output: 在电商行业中,GMV(总销售额)是一个非常重要的指标,用于衡量业务的整体健康…...
山东做网站建设的好公司排名/网站制作代码
这里介绍一种基于MQ的RPC方案—ESB(Enterprise Service Bus 企业服务总线)的实现方式。 1.ESB的由来 银行系统间传输报文的格式并不统一,如果把报文转换的功能设置在请求方或者服务方,会随着系统数目的增加变得复杂难以维护。ESB…...
市场营销方案范文/成都网站排名生客seo怎么样
----start 存储过程之间可以相互调用,如何在它们之间传递数据呢?有以下3种方法。 一:通过输入输出参数传递数据 这是最简单的一种方式,不过值得注意的是,存储过程中的RETURN语句和其它程序设计语言中的return语句含义…...
手机网站开发 c/关键词歌曲
http://www.blogjava.net/Alpha/archive/2007/01/02.html转载于:https://blog.51cto.com/495798/1329292...
变态传奇手游/常用的seo工具
虽然Windows 10日臻完善和普及,可依然有很多用户在使用Windows 7,微软也在听取用户意见,前几天微软宣布DirectX 12下放到Windows 7,而微软也在准备Windows 7的新镜像。著名爆料WalkingCat在Twitter上爆料了微软新的Windows 7镜像的…...
框架网页模板下载/南宁百度seo建议
js如何引入css文件?1、使用document.write方式输出引入css的link标签在调用文件的顶部加入下例代码document.write();(注:有时你引用的文件还可能需要引用其他的js,我们需要将需要的那个js文件也以同样的方法引用进来)(相关课程推荐ÿ…...
哪个网站名片做的号/百度搜索风云榜游戏
根据 Mysql 里的字段 自动生成 类文件:但需要导入:require_once ./db/ez_sql_core.php;require_once ./db/ez_sql_mysql.php;上图 :核心代码:$meta mysql_fetch_field($rel);if($meta){if($meta->primary_key1){$this->primary_key $…...