Swift数组、字典和集合

原文出自:标哥的技术博客

前言

Swift语言提供Array、Set和Dictionary三种基本的集合类型用来存储集合数据。数组是有序的数据集;集合是无序无重复的数据集;而字典是无序的键值对数组集。

Swift的Array、Set和Dictionary类型被实现为泛型集合。因此,它所存储的元素的类型必须是一致的,同样,我们取出来的数据类型也是明确的。

集合的可变性(Mutability Of Collections)

如果创建一个Arrays、Sets或Dictionaries并且把它分配成一个变量,这个集合将会是可变的。这意味着我们可以在创建之后添加更多或移除已存在的数据项,或者改变集合中的数据项。

如果我们把Arrays、Sets或Dictionaries分配成常量,那么它就是不可变的,它的大小和内容都不能被改变。

若我们确定集合不需要改变,那么我们应该使用不可变集合,也就是使用let声明,那样编译器会为我们优化。

// 在swift中要让Array、Set、Dictionary类型的变量是可变的,用var声明就可以了。
// 如果不希望可变,用let声明即可。
let immutableArrray = [Int]()

// 提示:error: immutable value of type '[Int]' only has mutating
// members named 'append'
//immutableArrray.append(12)

// OK
var mutableArray = [Int]()
mutableArray.append(12)

数组(Arrays)

数组使用有序列表存储同一类型的多个值,相同的值可以多次出现在一个数组的不同位置中。我们需要明确,数组是有序的,元素类型是相同的。

Swift中的Array与Foundation中的NSArray是桥接的,可以相互转换。

创建一个空数组(Create An Empty Array)

由于Swift中的数组是泛型,因此必须指定元素的数据类型:

// 使用构造语法来创建一个由特定数据类型构成的空数组:
// 方括号中必须指定类型,因为Array是一种泛型
var emptyArray = [Int]()

// 也可以使用结构体Array的构造写法
var anotherEmptyArray = Array<Int>()

// 如果之前类型明确了,直接再用[]即可.一样是Int类型的元素,是可推断出来的
emptyArray = []

创建带默认值的数组(Creating An Array With A Default Value)

Swift提供了如下方法,可以创建带有默认值的数组,这个构造方法是使用count个指定元素来初始化:

/// Construct a Array of `count` elements,each initialized to
/// `repeatedValue`.
public init(count: Int,repeatedValue: Element)

例如:

var threeDoubles = [Double](count: 3,repeatedValue:0.0)
// threeDoubles 是一种 [Double] 数组,等价于 [0.0,0.0,0.0]

数组相加来创建数组(Creating An Array By Adding Two Array Togeter)

两个数组能够通过加号+来创建一个合并的数组,是因为苹果为我们提供了这样的方法:

public func +<RRC1 : RangeReplaceableCollectionType,RRC2 : RangeReplaceableCollectionType where RRC1.Generator.Element == RRC2.Generator.Element>(lhs: RRC1,rhs: RRC2) -> RRC1

这是个泛型函数,要求类型RRC1和RRC2是遵守RangeReplaceableCollectionType协议的,并且这两个集合的元素类型要求相同。而数组是遵守RangeReplaceableCollectionType协议的,因此可以通过此方法将两个数组相加。

例如:

// anotherThreeDoubles 被推断为 [Double],等价于 [2.5,2.5,2.5]
var anotherThreeDoubles = Array(count: 3,repeatedValue: 2.5)

// sixDoubles 被推断为 [Double],等价于 [0.0,2.5]
var sixDoubles = threeDoubles + anotherThreeDoubles

用数组字面量构造数组(Creating An Array With An Array Literal)

我们可以使用字面量数组来进行数组构造,这是一种用一个或者多个数值构造数组的简单方法。字面量是一系列由逗号分割并由方括号包含的数值:

// shoppingList 已经被构造并且拥有两个初始项。
var shoppingList: [String] = ["Eggs","Milk"]

由于类型是明确的,因此我们可以交由编译器来推断类型数组的类型:

var shoppingList = ["Eggs","Milk"]

访问和修改数组(Accessing And Modifying An Array)

常见的数组访问和修改操作有:

  • 获取数组元素个数
  • 判断数组是否为空
  • 数组追加元素
  • 数组在某个位置插入元素
  • 数组在某个范围插入元素

数组元素个数

获取数组元素的个数,可通过count属性获取:

// 打印结果:"The shopping list contains 2 items."
print("The shopping list contains \(shoppingList.count) items.")

数组判断是否为空

判断数组是否为空,可以通过isEmpty属性判断,也可以通过count判断:

if shoppingList.isEmpty {
    print("The shopping list is empty.")
} else {
    print("The shopping list is not empty.")
}

// 或者通过count属性
if shoppingList.count == 0 {
    print("The shopping list is empty.")
} else {
    print("The shopping list is not empty.")
}

数组末尾追加元素

常用的有以下几种方法:

  • 通过append()追加
  • 通过appendContentsOf()追加
  • 通过+=追加

我们先来分析一下数组结构体所提供的方法:

/// Append the elements of `newElements` to `self`.
///
/// - Complexity: O(*length of result*).
public mutating func appendContentsOf<S : SequenceType where S.Generator.Element == Element>(newElements: S)
/// Append the elements of `newElements` to `self`.
///
/// - Complexity: O(*length of result*).
public mutating func appendContentsOf<C : CollectionType where C.Generator.Element == Element>(newElements: C)

我们可以看到对于第一个appendContentsOf方法要求参数S是遵守了SequenceType

var array = [1,2]

// 追加单个元素
array.append(3)

// 追加一个数组
array += [4,5]

// 追加一个集合
array.appendContentsOf([6,7])

// 追加一个序列:1,2,3,4,5,6
array.appendContentsOf(1...6)

数组插入元素

数组提供了insert(_:at:)方法插入数据:

/// Insert `newElement` at index `i`. /// /// - Requires: `i <= count`. /// /// - Complexity: O(`count`). public mutating func insert(newElement: Element,atIndex i: Int)

那么可以通过调用来插入数据:

var array = [1,2]
array.insert(55,atIndex: 2)

数组修改值

我们也可以通过下标获取或者修改数据,我们先看看声明:

// 这个方法是在index位置插入数据或者获取index位置的数据
public subscript (index: Int) -> Element

// 这个方法是在指定的range插入多个数据或者获取指定range的数据
public subscript (subRange: Range<Int>) -> ArraySlice<Element>

通过下标获取或者修改值:

// 修改元素值,可以通过索引
array[0] = 100
// 获取
print(array[0])

// 可以修改指定范围的值
array[1..<4] = [77,88,99]
// 获取
print(array[1..<4])

也可以调用replaceRange(_:with:)来替换值:

array.replaceRange(1...2,with: [10,12])

数组移除元素

先看看苹果所提供的方法:

// 移除最后一个元素
public mutating func removeLast() -> Element

// 某个指定位置的元素
public mutating func removeAtIndex(index: Int) -> Element

// 移除某个范围
public mutating func removeRange(subRange: Range<Self.Index>)

// 移除前n个
public mutating func removeFirst(n: Int)

// 移除第一个
public mutating func removeFirst() -> Self.Generator.Element

// 清空
public mutating func removeAll(keepCapacity keepCapacity: Bool = default)

看看如何调用:

// 删除第一个
let element = array.removeAtIndex(0)

// 删除最后一个
let lastElement = array.removeLast()

// 删除所有元素,但是内存不释放,空间容量保留
array.removeAll(keepCapacity: true)

// 删除所有元素,且不保留原来的空间
array.removeAll(keepCapacity: false)

// 移除位置1、2、3的元素
array.removeRange(1...3)

// 移除第一个元素
let first = array.removeFirst()

// 移除前三个元素
array.removeFirst(3)

数组遍历

常用的数组遍历有几种。

第一种,只获取元素值的for-in遍历:

for item in array {
    print(item)
}

第二种,获取元素及索引的for-in遍历:

for (index,value) in array.enumerate() {
  print("index: \(index),value = \(value)")
}

集合(Sets)

集合(Set)用来存储相同类型并且没有确定顺序的值。当集合元素顺序不重要时或者希望确保每个元素只出现一次时可以使用集合而不是数组。

为了存储在集合中,该类型必须是可哈希化的。也就是说,该类型必须提供一个方法来计算它的哈希值。一个哈希值是Int类型的,它和其他的对象相同,其被用来比较相等与否,比如a==b,它遵循的是a.hashValue == b.hashValue。Swift 的所有基本类型(比如String,Int,Double和Bool)默认都是可哈希化的,它可以作为集合的值或者字典的键值类型。没有关联值的枚举成员值(在枚举有讲述)默认也是可哈希化的。

使用自定义的类型作为集合的值或者是字典的键值类型时,需要使自定义类型服从Swift标准库中的Hashable协议。服从Hashable协议的类型需要提供一个类型为Int的取值访问器属性hashValue。这个由类型的hashValue返回的值不需要在同一程序的不同执行周期或者不同程序之间保持相同。 因为hashable协议服从于Equatable协议,所以遵循该协议的类型也必须提供一个”是否等”运算符(\==)的实现。这个Equatable协议需要任何遵循的\==的实现都是一种相等的关系。也就是说,对于a,b,c三个值来说,\==的实现必须满足下面三种情况:

  • a\==a(自反性)
  • a\==b 可推出 b\==a(对称性)
  • a\==b&&b\==c 可推出 a\==c(传递性)

空集合(Empty Set)

Swift中的Set类型被写为Set<Element>,这里的Element表示Set中允许存储的类型,和数组不同的是,集合没有等价的简化形式。

var emptySet = Set<Int>()
print(emptySet.count) // 0

// 当变量已经有明确的类型时,再用空数组来初始化[],其类型也是可推断的
emptySet = []// 类型为Set<Int>()

初始化集合(Initializing An Empty Set)

可以直接使用数组字面量来初始化集合:

// 用数组构造集合
var favSet: Set<String> = ["milk","egg"]

// 如果元素都是相同类型,带有初始化,可以省略类型
var favSet1: Set = ["good milk","bad egg"]

使用集合可以非常好地解决重复问题:

// 重复的数据会被自动去重
var favSet: Set<String> = ["milk","egg","milk"]
print(favSet.count)// 2

访问集合(Accessing A Set)

获取集合元素的个数,可以通过count只读属性获取,其时间复杂度为O(1),也就是常量,因此效率是极高的。想想时间复杂度能达到O(1),说明内部并不是列表,而是类似字典那样的哈希表,不过具体内部是如何,这里不细说,还得去查看源代码才能知晓。

/// The number of members in the set.
///
/// - Complexity: O(1).
public var count: Int { get }

调用就很方便了,效率又非常地高:

let count = favSet.count

我们还可以通过isEmpty属性判断是否为空:

// 官方声明如下:
/// `true` if the set is empty.
public var isEmpty: Bool { get }

// 判断是否为空集
if favSet.isEmpty {
  print("empty set")
} else {
  print("non empty set")
}

判断元素是否在集合中:

// 判断是否包含元素
if favSet.contains("wahaha") {
  print("fav set contains wahaha")
} else {
  print("fav set doesn\'t not contain wahaha")
}

遍历集合(Iterating Over A Set)

遍历很少能离开得了for-in语法:

// 遍历一个set。使用for-in
for value in favSet {
  print(value)// 这是无序的
}

遍历集合,同时使集合是有序的:

// 要使之有序 // sort方法
for value in favSet.sort({ (e,ee) -> Bool in
  return e > ee // 由我们指定排序类型desc(降序)
}) {
  // milk
  // egg
  print(value)
}
 // 或者: // 或者直接使用sort无参数(默认为asc升序)
for value in favSet.sort() {
  // egg
  // milk
  print(value)
}

当然还可以使用最原始的方法来遍历:

for var i = favSet.startIndex; i != favSet.endIndex; i = i.successor() { print("for-i-in" + favSet[i]) }

集合基本操作(Fundamental Set Operations)

集合的基本操作有:

  • 求交集:使用intersect(_:)方法根据两个集合中都包含的值创建的一个新的集合。
  • 求非交集:使用exclusiveOr(_:)方法根据在一个集合中但不在两个集合中的值创建一个新的集合。
  • 求并集:使用union(_:)方法根据两个集合的值创建一个新的集合。
  • 求差集:使用subtract(_:)方法根据不在该集合中的值创建一个新的集合。
let set1: Set = [1,2,3,4,5]
let set2: Set = [1,8]

// 求两个集合的交集
// 3,1,4
print(set1.intersect(set2))

// 求两个集合的并集
// 1,5
print(set1.union(set2).sort())

// 求集合set1去掉set1与set2的交集部分
// 2,5
print(set1.subtract(set2).sort())

// 求集合set1与set2的并集 去掉 集合set1与set2的交集 部分
// 2,5,8
print(set1.exclusiveOr(set2).sort())

集合成员关系(Relationships Of Set members)

  • 使用\==来判断两个集合是否包含全部相同的值。
  • 使用isSubsetOf(_:)方法来判断是否为子集
  • 使用isSupersetOf(_:)方法来判断是否为超集
  • 使用isStrictSubsetOf(_:)或者isStrictSupersetOf(_:)方法来判断一个集合是否是另外一个集合的子集合或者父集合并且两个集合并不相等。
  • 使用isDisjointWith(_:)方法来判断两个集合是否不含有相同的值。

从图中可以看出:

  1. 集合a全部包含b,也就是说b是a的子集
  2. 集合a与集合b相交,但是a与b不完全包含
  3. 集合c与集合b完全没有交集
let set1: Set = [1,8]

// false
// set1并没有全部被set2包含
print(set1.isSubsetOf(set2))

let set3: Set = [1,5]

// true
// set3全部在set1中
print(set3.isSubsetOf(set1))

// true
// set1真包含set3,因此set1是set3的超集
print(set1.isSupersetOf(set3))

// true
// set1是set3的严格超集,因为Set1真包含set3且set1 != set3
print(set1.isStrictSupersetOf(set3))

// true
// set1真包含set3,且set1 != set3,因此set3是set1严格的真子集
print(set3.isStrictSubsetOf(set1))

let set4: Set = [1,2]

// false
// 因为set3和set4的元素是一样的,即相等
print(set4.isStrictSubsetOf(set3))

// false
// 这两个集合中有相同的元素
print(set3.isDisjointWith(set4))

let set5:Set = [9,6]

// true
// set5和set4没有相同的元素
print(set5.isDisjointWith(set4))

字典(Dictonaries)

字典是一种存储多个相同类型的值的容器。每个值都关联唯一的键,键作为字典中的这个值数据的标识符。和数组中的数据项不同,字典中的数据项并没有顺序的。我们在需要通过key访问数据的时候使用字典,这种方法很大程度上和我们在现实世界中使用字典查字义的方法一样。

Swift中的Dictionary与Foundation中的NSDictionary是桥接的,可以互相转换使用。

我们先来看看字典的结构定义:

/// A hash-based mapping from `Key` to `Value` instances. Also a
/// collection of key-value pairs with no defined ordering.
public struct Dictionary<Key : Hashable,Value> : CollectionType,DictionaryLiteralConvertible

它是基于哈希表从key到value实例的映射,它的键值是无序的。要求key是遵守Hashable的。
其正规语法应该是:Dictonary<key,value>

创建空字典(Creating An Empty Dictionary)

// 创建空字典
var emptyDict = [Int: String]()

// 或者
emptyDict = Dictionary<Int,String>()

// 当创建过emptyDict后,再用[:]又成为一个空字典
emptyDict = [:]

初始化字典(Initializing A Dictionary)

// 多个键值对用逗号分割
// 通过类型推断是可以推断出来类型为[String: String]
var dict = ["A": "Apple","B": "Bubble"]

// 手动指明数据类型
var airports: [String: String] = ["YYZ": "Toronto Pearson","DUB": "Dublin"]

声明不可变字典:

// 如果不希望字典可变,用let声明即可
let immutableDict = ["A": "Apple","B": "Bubble"]
// 无法调用,因为是不可变的
//immutableDict.updateValue("App",forKey: "A")
//immutableDict += ["AB:","Apple Bubble"]

访问和修改字典(Accessing And Modifying A Dictionary)

我们可以通过字典的方法和属性来访问和修改字典,或者通过使用下标语法。

判断是否为空字典:

if dict.isEmpty {
  print("dict is an empty dictionary")
} else {
  print("dict is not an empty dictionary")
}

// 或者通过获取字典元素的个数是否为0
if dict.count == 0 {
  print("dict is an empty dictionary")
} else {
  print("dict is not an empty dictionary")
}

可以直接通过下标获取元素:

// 通过key直接获取
var apple = dict["A"]

// 获取索引获取(key,value),再获取值
// 由于字典中的(key,value)是元组,因此可以直接通过点语法获取
let startKeyValue = dict[dict.startIndex]
let value = startKeyValue.1

// 读取时,判断是否有值
if let value = dict["BB"] {
  print("value is \(value)")
} else {
  // 输入这行
  print("The key BB doesn\'t not exist in dict")
}

可以直接通过下标来修改或者增加值:

// 修改,如果不存在,则会增加,否则更新值
dict["A"] = "Good Apple"

// 或者用API,如果不存在,则会增加,否则只是更新值
if let oldValue = dict.updateValue("Dog",forKey: "D") {
  print("The old value is \(oldValue)")
} else {
  // 输出这行
  print("The key D does\'t not exist before update")
}

移除元素:

// 通过下标语法移除元素
dict["D"] = nil

// 或者通过调用removeValueForKey方法来移除
if let removedValue = dict.removeValueForKey("D") {
  print("The removed value is \(removedValue)")
} else {
  print("The key D doesn'\t exist in dict,can\' be removed.")
}

// 或者清空字典:
dict.removeAll()

字典遍历(Iterate Over A Dictionary)

字典中每个元素是一个键值对,而这个键值对其实就是一个元组:

// 用for-in遍历,形式为(key,value)
for (key,value) in dict {
  print("\(key): \(value)")
}

可以通过遍历所有的key:

// 可以遍历key
for key in dict.keys {
  print("\(key): \(dict[key])")
}

也可以遍历所有的值:

for value in dict.values {
  print("\(value)")
}

字典值或者键转换成数组

如果不清楚Array有这么一个构造函数,那么您可能会手动写代码去遍历,但是事实上我们可以直接使用构造函数来实现的。我们知道字典的keys和values属性返回来的是LazyMapCollection<key,value>类型,并不是我们直接需要到的数据,因此我们有的时候需要转换成我们直接能使用的数据,这时候就需要这么做的:

// 获取所有的值
let values = [String](dict.values)

// 获取所有的键
let keys = [String](dict.keys)

写在最后

本篇博文是笔者在学习Swift 2.1的过程中记录下来的,可能有些翻译不到位,还请指出。另外,所有例子都是笔者练习写的,若有不合理之处,还望指出。

学习一门语言最好的方法不是看万遍书,而是动手操作、动手练习。如果大家喜欢,可以关注哦,尽量2-3天整理一篇Swift 2.1的文章。这里所写的是基础知识,如果您已经是大神,还请绕路!

文章并非纯翻译,而是练习语法而记录下来的内容

关注我

如果在使用过程中遇到问题,或者想要与我交流,可加入有问必答QQ群:324400294

关注微信公众号:iOSDevShares

关注新浪微博账号:标哥Jacky

支持并捐助

如果您觉得文章对您很有帮助,希望得到您的支持。您的捐肋将会给予我最大的鼓励,感谢您的支持!

支付宝捐助 微信捐助

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


软件简介:蓝湖辅助工具,减少移动端开发中控件属性的复制和粘贴.待开发的功能:1.支持自动生成约束2.开发设置页面3.做一个浏览器插件,支持不需要下载整个工程,可即时操作当前蓝湖浏览页面4.支持Flutter语言模板生成5.支持更多平台,如Sketch等6.支持用户自定义语言模板
现实生活中,我们听到的声音都是时间连续的,我们称为这种信号叫模拟信号。模拟信号需要进行数字化以后才能在计算机中使用。目前我们在计算机上进行音频播放都需要依赖于音频文件。那么音频文件如何生成的呢?音频文件的生成过程是将声音信息采样、量化和编码产生的数字信号的过程,我们人耳所能听到的声音频率范围为(20Hz~20KHz),因此音频文件格式的最大带宽是20KHZ。根据奈奎斯特的理论,音频文件的采样率一般在40~50KHZ之间。奈奎斯特采样定律,又称香农采样定律。...............
前言最近在B站上看到一个漂亮的仙女姐姐跳舞视频,循环看了亿遍又亿遍,久久不能离开!看着小仙紫姐姐的蹦迪视频,除了一键三连还能做什么?突发奇想,能不能把舞蹈视频转成代码舞呢?说干就干,今天就手把手教大家如何把跳舞视频转成代码舞,跟着仙女姐姐一起蹦起来~视频来源:【紫颜】见过仙女蹦迪吗 【千盏】一、核心功能设计总体来说,我们需要分为以下几步完成:从B站上把小姐姐的视频下载下来对视频进行截取GIF,把截取的GIF通过ASCII Animator进行ASCII字符转换把转换的字符gif根据每
【Android App】实战项目之仿抖音的短视频分享App(附源码和演示视频 超详细必看)
前言这一篇博客应该是我花时间最多的一次了,从2022年1月底至2022年4月底。我已经将这篇博客的内容写为论文,上传至arxiv:https://arxiv.org/pdf/2204.10160.pdf欢迎大家指出我论文中的问题,特别是语法与用词问题在github上,我也上传了完整的项目:https://github.com/Whiffe/Custom-ava-dataset_Custom-Spatio-Temporally-Action-Video-Dataset关于自定义ava数据集,也是后台
因为我既对接过session、cookie,也对接过JWT,今年因为工作需要也对接了gtoken的2个版本,对这方面的理解还算深入。尤其是看到官方文档评论区又小伙伴表示看不懂,所以做了这期视频内容出来:视频在这里:本期内容对应B站的开源视频因为涉及的知识点比较多,视频内容比较长。如果你觉得看视频浪费时间,可以直接阅读源码:goframe v2版本集成gtokengoframe v1版本集成gtokengoframe v2版本集成jwtgoframe v2版本session登录官方调用示例文档jwt和sess
【Android App】实战项目之仿微信的私信和群聊App(附源码和演示视频 超详细必看)
用Android Studio的VideoView组件实现简单的本地视频播放器。本文将讲解如何使用Android视频播放器VideoView组件来播放本地视频和网络视频,实现起来还是比较简单的。VideoView组件的作用与ImageView类似,只是ImageView用于显示图片,VideoView用于播放视频。...
采用MATLAB对正弦信号,语音信号进行生成、采样和内插恢复,利用MATLAB工具箱对混杂噪声的音频信号进行滤波
随着移动互联网、云端存储等技术的快速发展,包含丰富信息的音频数据呈现几何级速率增长。这些海量数据在为人工分析带来困难的同时,也为音频认知、创新学习研究提供了数据基础。在本节中,我们通过构建生成模型来生成音频序列文件,从而进一步加深对序列数据处理问题的了解。
基于yolov5+deepsort+slowfast算法的视频实时行为检测。1. yolov5实现目标检测,确定目标坐标 2. deepsort实现目标跟踪,持续标注目标坐标 3. slowfast实现动作识别,并给出置信率 4. 用框持续框住目标,并将动作类别以及置信度显示在框上
数字电子钟设计本文主要完成数字电子钟的以下功能1、计时功能(24小时)2、秒表功能(一个按键实现开始暂停,另一个按键实现清零功能)3、闹钟功能(设置闹钟以及到时响10秒)4、校时功能5、其他功能(清零、加速、星期、八位数码管显示等)前排提示:前面几篇文章介绍过的内容就不详细介绍了,可以看我专栏的前几篇文章。PS.工程文件放在最后面总体设计本次设计主要是在前一篇文章 数字电子钟基本功能的实现 的基础上改编而成的,主要结构不变,分频器将50MHz分为较低的频率备用;dig_select
1.进入官网下载OBS stdioOpen Broadcaster Software | OBS (obsproject.com)2.下载一个插件,拓展OBS的虚拟摄像头功能链接:OBS 虚拟摄像头插件.zip_免费高速下载|百度网盘-分享无限制 (baidu.com)提取码:6656--来自百度网盘超级会员V1的分享**注意**该插件必须下载但OBS的根目录(应该是自动匹配了的)3.打开OBS,选中虚拟摄像头选择启用在底部添加一段视频录制选择下面,进行录制.
Meta公司在9月29日首次推出一款人工智能系统模型:Make-A-Video,可以从给定的文字提示生成短视频。基于**文本到图像生成技术的最新进展**,该技术旨在实现文本到视频的生成,可以仅用几个单词或几行文本生成异想天开、独一无二的视频,将无限的想象力带入生活
音频信号叠加噪声及滤波一、前言二、信号分析及加噪三、滤波去噪四、总结一、前言之前一直对硬件上的内容比较关注,但是可能是因为硬件方面的东西可能真的是比较杂,而且需要渗透的东西太多了,所以学习进展比较缓慢。因为也很少有单纯的硬件学习研究,总是会伴随着各种理论需要硬件做支撑,所以还是想要慢慢接触理论学习。但是之前总找不到切入点,不知道从哪里开始,就一直拖着。最近稍微接触了一点信号处理,就用这个当作切入点,开始接触理论学习。二、信号分析及加噪信号处理选用了matlab做工具,选了一个最简单的语音信号处理方
腾讯云 TRTC 实时音视频服务体验,从认识 TRTC 到 TRTC 的开发实践,Demo 演示& IM 服务搭建。
音乐音频分类技术能够基于音乐内容为音乐添加类别标签,在音乐资源的高效组织、检索和推荐等相关方面的研究和应用具有重要意义。传统的音乐分类方法大量使用了人工设计的声学特征,特征的设计需要音乐领域的知识,不同分类任务的特征往往并不通用。深度学习的出现给更好地解决音乐分类问题提供了新的思路,本文对基于深度学习的音乐音频分类方法进行了研究。首先将音乐的音频信号转换成声谱作为统一表示,避免了手工选取特征存在的问题,然后基于一维卷积构建了一种音乐分类模型。
C++知识精讲16 | 井字棋游戏(配资源+视频)【赋源码,双人对战】
本文主要讲解如何在Java中,使用FFmpeg进行视频的帧读取,并最终合并成Gif动态图。
在本篇博文中,我们谈及了 Swift 中 some、any 关键字以及主关联类型(primary associated types)的前世今生,并由浅及深用简明的示例向大家讲解了它们之间的奥秘玄机。