一、简介

  由于Spark主要是由Scala编写的,虽然Python和R也各自有对Spark的支撑包,但支持程度远不及Scala,所以要想更好的学习Spark,就必须熟练掌握Scala编程语言,Scala与Java较为相似,且在Scala中可以调用很多Java中的包,本文就将针对Scala中的基础数据结构、循环体以及错误处理机制进行基础的介绍;

二、基础数据类型与数据结构

2.1基础数据类型

  Scala包括了8种基础数据类型,基本信息如下表:

基本类型 取值范围或示例
Byte -128~127
Char U+0000~U+FFFF
Short -32768~32767
Int -2147483648~2147483647
Long -9223372036854775808~9223372036854775807
Float 单精度浮点数,如0.1f
Double 双精度浮点数,如0.11
Boolean true或false

  String也属于Scala基本数据类型,归属于java.lang包,其余的数据类型都是Scala自带基础类型包的成员,且在Scala中基本类型包与java.lang包是默认导入的。

2.2 Scala变量声明

  和java类似,Scala中的变量需要在创建时进行声明,有var和val两种声明方式,其中val类型变量定义后不可以重新赋值,而var类型变量声明之后可以自由赋新值,下面在Scala控制台中演示:

//利用val进行变量的声明
scala> val x = 0
x: Int = 0 scala> x = 5
<console>:11: error: reassignment to val
x = 5
^
//利用var进行变量的声明
scala> var x = 0
x: Int = 0 scala> x = 8
x: Int = 8

可以看到,val声明后的变量不可重新赋值,而var则可以。

  Scala中的变量声明有两种形式,一种是在声明变量时指出变量的具体类型:

scala> val x:Int=10
x: Int = 10 scala> val y:Double=1.00
y: Double = 1.0 scala> val z:String="scala"
z: String = scala

  而事实上,即使你在Scala中声明变量时不进行类型的指定,Scala内部也会根据你输入数据的具体类型进行判断,来自动分配数据类型,这是第二种变量声明的方式:

scala> val x=10
x: Int = 10 scala> val y=1.0f
y: Float = 1.0 scala> val z="spark"
z: String = spark

2.3 算数操作符、关系运算符与逻辑运算符

  Scala像很多其他成熟的编程语言一样,具有丰富的内置运算符,且在Scala中操作符也被视为函数,即可以通过对象.操作符()的方式使用,Scala中的常用运算符如下:

运算符 描述
+ 加运算
- 减运算
* 乘运算
/ 除运算
% 求模运算,返回余数

  而Scala中的关系运算符如下:

运算符 描述
== 判断两个对象是否相等
!= 判断两个对象是否不等
> 判断是否左大于右
< 判断是否左小于右
>= 判断是否左大于等于右
<= 判断是否左小于等于右

  Scala中的逻辑运算符如下:

运算符 描述
&& 逻辑与
|| 逻辑或
! 逻辑非

  Scala中的赋值运算符如下:

运算符 描述
= 将右侧的值赋给左对象
+= 先做加法再赋值
-= 先做减法再赋值
*= 先做乘法再赋值
/= 先做除法再赋值
%= 先做求模取余再赋值

2.4基础数据结构

2.4.1定长数组与可变数组

基本概念:

  在Scala中,数组分为可变(mutable)和不可变(immutable)数组,默认情况下定义的数组为不可变数组,若要定义可变数组,需要导入包scala.collection.mutable.ArrayBuffer,下面是一个示例:

//定义不可变长数组
scala> var array = Array(1,2,3,4)
array: Array[Int] = Array(1, 2, 3, 4) //导入可变长数组所在包
scala> import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.ArrayBuffer //创建可变长数组
scala> var arrayBuffer = ArrayBuffer(1,2,3,4)
arrayBuffer: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4)

数组相关方法:

  1.索引

  对于数组,我们使用 数组名(n) 的方式来索引其从第0位开始第n+1个元素:

scala> var array=Array("I","You","He","Her","It")
array: Array[String] = Array(I, You, He, Her, It) scala> array(1)
res0: String = You

  2.将不可变数组转换为可变数组

  我们使用.toBuffer来完成Array到ArrayBuffer的转变:

scala> var array = Array(1,2,3)
array: Array[Int] = Array(1, 2, 3) scala> array.toBuffer
res1: scala.collection.mutable.Buffer[Int] = ArrayBuffer(1, 2, 3)

  3.获取数组长度

  我们使用.length方法来获取数组的长度:

scala> var array10 = new Array[Int](10)
array10: Array[Int] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0) scala> array10.length
res2: Int = 10

  4.在可变数组末尾添加元素

  我们用 += 的方式为可变长数组在其末尾添加单个或多个元素:

//创建可变长数组
scala> var arrayBuffer = ArrayBuffer(1,2,3)
arrayBuffer: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3) //在创建好的可变长数组的末尾添加单个元素4
scala> arrayBuffer += 4
res3: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4) //在创建好的可变长数组的末尾添加多个元素
scala> arrayBuffer += (5,6,7)
res4: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5, 6, 7)

  5.在可变长数组末尾追加任何数组

scala> var buff1 = ArrayBuffer(1,2,3)
buff1: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3) scala> var buff2 = ArrayBuffer(4,5)
buff2: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(4, 5) scala> buff1 ++= buff2
res1: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5)

  6.移除最末端n个元素

  我们使用.trimEnd(n)来移除数组末端的n个元素:

scala> var arrayBuffer = ArrayBuffer(1,2,3,4,5,6)
arrayBuffer: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5, 6) scala> arrayBuffer.trimEnd(3) scala> arrayBuffer
res1: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3)

  7.移除最前端n个元素

  我们使用.trimStart(n)来移除数组前端的n个元素:

scala> var arrayBuffer = ArrayBuffer(1,2,3,4,5,6)
arrayBuffer: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5, 6) scala> arrayBuffer.trimStart(3) scala> arrayBuffer
res1: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(4, 5, 6)

  8.移除数组中指定位置的元素

  我们使用.remove(n)来移除数组中下标为n的元素:

scala> var arrayBuffer = ArrayBuffer(0,1,2,3,4,5)
arrayBuffer: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(0, 1, 2, 3, 4, 5) scala> arrayBuffer.remove(3)
res2: Int = 3 scala> arrayBuffer
res3: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(0, 1, 2, 4, 5)

  9.从数组中指定位置开始移除若干个元素

  我们依旧使用.remove(n,m)来移除数组中下标为n的元素开始往后的m个元素:

scala> var arrayBuffer = ArrayBuffer(0,1,2,3,4,5)
arrayBuffer: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(0, 1, 2, 3, 4, 5) scala> arrayBuffer.remove(3)
res2: Int = 3 scala> arrayBuffer
res3: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(0, 1, 2, 4, 5) scala> var arrayBuffer = ArrayBuffer(0,1,2,3,4,5)
arrayBuffer: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(0, 1, 2, 3, 4, 5) scala> arrayBuffer.remove(2,2) scala> arrayBuffer
res5: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(0, 1, 4, 5)

2.4.2 Map映射

  与Python中的字典相似,Scala中的映射就是键值对的集合Map,默认情况下Scala中同样是使用不可变的映射,想要使用可变的映射就必须导入scala.collection.mutable.Map类。

  1.定义映射

  我们用->连接键值,左边为键,右边为值,键唯一:

scala> var DemoMap = Map("Scala"->1,"Python"->2,"R"->3)
DemoMap: scala.collection.immutable.Map[String,Int] = Map(Scala -> 1, Python -> 2, R -> 3)

  2.Map映射的索引

  直接通过调用键来获取对应的值:

scala> DemoMap("Python")
res1: Int = 2

  3.判断映射中是否包含某个键的键值对

  我们使用.contains(键名)来判断某个映射中是否包含指定键名的键值对:

scala> DemoMap.contains("SQL")
res2: Boolean = false

  4.按下标获取键值对

  我们使用.drop(n)来获取指定映射中下标为2及其之后下标的键值对:

scala> DemoMap.drop(1)
res7: scala.collection.immutable.Map[String,Int] = Map(Python -> 2, R -> 3)

  5.构造可变映射

  为了构造可变的映射,我们需要导入相关包或在Map定义时输入完整路径,这里建议后者:

scala> var DemoMap = scala.collection.mutable.Map("Python"->1,"Java"->2,"R"->3)
DemoMap: scala.collection.mutable.Map[String,Int] = Map(R -> 3, Java -> 2, Python -> 1)

  6.为可变映射更新或新增键值对

//更新已有的可变Map映射中指定键的值,若不存在此键则创造新键值对
scala> DemoMap("Julia") = 100 scala> DemoMap
res1: scala.collection.mutable.Map[String,Int] = Map(R -> 3, Julia -> 100, Java -> 2, Python -> 1)

  7.提取Map映射中的键集合

  我们使用.keySet来提取Map映射中的键名集合:

scala> DemoMap.keySet
res3: scala.collection.Set[String] = Set(R, Julia, Java, Python)

  8.提取Map映射中的值集合

scala> DemoMap.values
res4: Iterable[Int] = HashMap(3, 100, 2, 1)

  9.逐个的获取Map映射中的键值对信息

scala> for((k,v) <- DemoMap)println(k,"->",v)
(R,->,3)
(Julia,->,100)
(Java,->,2)
(Python,->,1)

2.4.3 Tuple元组

  与Python中的元组类似,Scala中的tuple元组也是圆括号包住的,可以存放不同类型的若干元素,且无论是用var还是val方式声明,元组中的元素都不可改变,且元组对内部元素的索引比较特别,是通过._n来索引其内部第n个元素(这里不从0开始):

//声明一个元组
scala> var tuple1 = (1,2,"3",4.0f,5.0)
tuple1: (Int, Int, String, Float, Double) = (1,2,3,4.0,5.0) //对元组中的第一个元素进行索引
scala> tuple1._1
res0: Int = 1 //尝试修改元组中的固有元素
scala> tuple1._1 = 3
<console>:11: error: reassignment to val
tuple1._1 = 3

2.4.4 List列表

  也是和Python中的List类似,Scala中的列表被设计来存放各种类型的元素,且Scala中的列表类型有三种模式,一种是当列表内部元素类型统一时,如List[Int],一种是当列表中同时包含几种不同类型元素时,为List[Any],最后一种是当列表中不存放任何元素时,为List[Nothing]:

  1.定义不同的列表

scala> var list1 = List(1,2,3)
list1: List[Int] = List(1, 2, 3) scala> var list1 = List("1","2")
list1: List[String] = List(1, 2) scala> var list1 = List("1",2)
list1: List[Any] = List(1, 2) scala> var list1 = List()
list1: List[Nothing] = List()

  2.构建多维列表

  在Scala中,和Python类似,也可以通过多层列表的嵌套来制造多维列表:

//声明一个二维列表
scala> var list1 = List(List(1,1),List(2,3))
list1: List[List[Int]] = List(List(1, 1), List(2, 3)) scala> list1(0)(1)
res0: Int = 1

  3.列表的拼接方式

  在Scala中,我们可以通过:::运算符或List.concat()来为已有的列表串联上新的列表:

scala> var list1 = List(1,2,3)
list1: List[Int] = List(1, 2, 3) scala> var list2 = List(4,5)
list2: List[Int] = List(4, 5) scala> list1:::list2
res0: List[Int] = List(1, 2, 3, 4, 5) scala> List.concat(list1,list2)
res1: List[Int] = List(1, 2, 3, 4, 5) scala> List.concat(list2,list1)
res2: List[Int] = List(4, 5, 1, 2, 3)

  4.列表的一些特殊索引方法

  和数组类似,列表中也有一些针对头尾若干元素的特殊的索引方式和特殊的判断列表属性的方法:

scala> var list1 = List(1,2,3,4)
list1: List[Int] = List(1, 2, 3, 4)
//使用.head方法获取第一个元素
scala> list1.head
res0: Int = 1
//使用.tail方法获取除第一个元素之外的全部元素
scala> list1.tail
res1: List[Int] = List(2, 3, 4)

2.4.5 Set集合

  和Python中的集合类似,Scala中的集合只允许不重复的若干元素存放在其中,因此可以用来去重,且Set集合分为不可改变的和可变的,即其本身能否被重新赋值或更改,默认情况下Scala中使用不可变的集合,若想使用可变集合就需要使用scala.collection.mutable.Set

//声明不可变长集合
scala> var set1 = Set(1,2,3,3,4)
set1: scala.collection.immutable.Set[Int] = Set(1, 2, 3, 4) //声明可变长集合
scala> var set2 = scala.collection.mutable.Set(1,2,2,3)
set2: scala.collection.mutable.Set[Int] = Set(1, 2, 3)

可以看到,无论是不可变长还是可变长集合,都完成了对输入元素的去重操作,且Set集合的head、tail、isEmpty操作与List基本一致,这里不再赘述。

  1.向集合中增减新元素

  我们使用.+()和.-()方法完成对集合中元素的添加或删减:

scala> set2.+(4)
res0: scala.collection.mutable.Set[Int] = Set(1, 2, 3, 4) scala> set2.-(2)
res1: scala.collection.mutable.Set[Int] = Set(1, 3)

  2.判断集合中是否包含指定的元素

  我们使用.contains()方法来判断集合中是否包含指定的元素:

scala> set2.contains(1)
res3: Boolean = true

  3.返回两个集合的交集、差

  我们使用.&()方法和.&~()方法来得到两个集合的交集和差集

scala> var set1 = Set(1,2,3,4)
set1: scala.collection.immutable.Set[Int] = Set(1, 2, 3, 4) scala> var set2 = Set(3,4,5,6)
set2: scala.collection.immutable.Set[Int] = Set(3, 4, 5, 6) scala> set1.&(set2)
res0: scala.collection.immutable.Set[Int] = Set(3, 4) scala> set1.&~(set2)
res1: scala.collection.immutable.Set[Int] = Set(1, 2)

  4.计算集合中满足指定条件的元素的个数

  我们使用.count()来实现此功能:

scala> var set1 = Set(1,2,2,3,4,5,5,5,6)
set1: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 3, 4) scala> set1.count(_ > 2)
res0: Int = 4

  5.集合转换为不可变长数组和可变长数组

scala> var set1 = Set("1","2","3")
set1: scala.collection.immutable.Set[String] = Set(1, 2, 3) scala> set1.toArray
res0: Array[String] = Array(1, 2, 3) scala> import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.ArrayBuffer scala> set1.toBuffer
res1: scala.collection.mutable.Buffer[String] = ArrayBuffer(1, 2, 3)

  6.快速判断集合中是否存在满足指定条件的元素

scala> var set1 = Set(1,2,3,4,5)
set1: scala.collection.immutable.Set[Int] = Set(5, 1, 2, 3, 4) scala> set1.exists(_ > 4)
res0: Boolean = true

  7.得到集合中所有元素的乘积

scala> var set1 = Set(1,2,3,4,5,6,7)
set1: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 7, 3, 4) scala> set1.product
res0: Int = 5040

  8.得到集合中所有元素的个数

scala> set1.product
res0: Int = 5040 scala> set1.size
res1: Int = 7

  9.得到一个集合中的最大值、最小值和所有元素之和

scala> var set1 = Set(1,2,3,4,5,6)
set1: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 3, 4) scala> set1.max
res0: Int = 6 scala> set1.min
res1: Int = 1 scala> set1.sum
res2: Int = 21

三、条件语句和循环语句

3.1条件语句

  Scala中的if条件语句与R中的相似,主要有两种形式:

  1、if(布尔表达式)  x else y

object Main {
//创建一个main方法
def main(args: Array[String]): Unit = {
var x = 1
if(x >= 0) println("Yes") else println("Nope")
}
}

  2、if(布尔表达式){

      ......

      } else {

      ......

      }

object Main {
def main(args: Array[String]): Unit = {
var x = 1
if(x >= 0){
println("Yse")
} else {
println("Nope")
}
}
}

  3、利用类似三目运算符的形式为变量赋值

scala> var x = 10
var y = if(x > 0)x else 100
x: Int = 10 scala> y: Int = 10

3.2循环语句

  Scala中的循环语句主要有三种:

  1、for循环

  Scala中for循环的语法格式为:

  for(变量<-集合){

    循环体

    }

  可以用m to n或m until n来定义循环遍历的集合,to表示左右都包括,until不包含右边:

scala> for(i <- 1 to 10){
println(i)
}
| | 1
2
3
4
5
6
7
8
9
10
scala> for(i <- 1 until 10){
println(i)
}
| | 1
2
3
4
5
6
7
8
9

  还可以在循环中添加条件语句:

scala> for(i <- 1 until 10 if i % 2 == 0){
println(i)
}
| | 2
4
6
8

  多个for循环结构体嵌套枚举:

scala> for(i <- 1 to 3;j <- 2 to 4)print(i*j+" ")
2 3 4 4 6 8 6 9 12

  利用for循环和关键词yield来返回新的序列:

scala> var seq1 = for(i <- 1 to 10 if i%3 == 0) yield i
seq1: scala.collection.immutable.IndexedSeq[Int] = Vector(3, 6, 9)

  2、while循环

  和R中的while语法相似,在Scala中while循环的格式同样为:

  while(条件表达式){

    循环体

 }

scala> var i = 1
while(i <= 10){
print(i+" ")
i += 1
}
i: Int = 1 scala> | | | 1 2 3 4 5 6 7 8 9 10

  由于在Scala中没有自带break、continue两个关键字,所以要实现continue的功能可以使用if语句来控制,而要实现break功能,则需要调取相关包scala.util.control.Breaks._:

import scala.util.control.Breaks._

object Main {
def main(args: Array[String]): Unit = {
var i = 1
while(true){
if(i >= 10){
println("stop")
break
}else{
i += 1
println(i)
}
}
}
}

  3.do-while

  do-while循环和while循环相似,区别在于do-while循环至少都会运行一次循环体内的代码,其使用格式如下:

  do{

  循环体内容

  }while(条件表达式)

import scala.util.control.Breaks._

object Main {
def main(args: Array[String]): Unit = {
var i = 1
do{
println(i)
i += 1
}while(i<=0)
}
}

3.3异常控制

  Scala中的异常控制与Java非常相似,处理抛出异常之外,还有捕获异常,这里我们只介绍捕获异常:

  Scala中捕获异常的格式如下:

  try{

... ...

  }catch{

      case ex:错误类型 => 捕获指定错误后的执行内容

}

在catch中捕获异常或错误,可以像上面一样指定错误类型与对应的处理方法,也可以用case ex:Exception => 的方式来更加泛型的捕获任何错误:

import scala.io.Source

object Main {
def main(args: Array[String]): Unit = {
try{
val file = Source.fromFile("F://test.txt")
val lines = file.getLines()
for(content <- lines){
println(content)
}
}catch{
case ex:Exception => println(ex)
}finally {
println("结束")
}
}
}

运行结果:

  以上就是本文的全部内容,如有笔误,望指出。

(数据科学学习手札45)Scala基础知识的更多相关文章

  1. (数据科学学习手札49)Scala中的模式匹配

    一.简介 Scala中的模式匹配类似Java中的switch语句,且更加稳健,本文就将针对Scala中模式匹配的一些基本实例进行介绍: 二.Scala中的模式匹配 2.1 基本格式 Scala中模式匹 ...

  2. (数据科学学习手札50)基于Python的网络数据采集-selenium篇(上)

    一.简介 接着几个月之前的(数据科学学习手札31)基于Python的网络数据采集(初级篇),在那篇文章中,我们介绍了关于网络爬虫的基础知识(基本的请求库,基本的解析库,CSS,正则表达式等),在那篇文 ...

  3. (数据科学学习手札55)利用ggthemr来美化ggplot2图像

    一.简介 R中的ggplot2是一个非常强大灵活的数据可视化包,熟悉其绘图规则后便可以自由地生成各种可视化图像,但其默认的色彩和样式在很多时候难免有些过于朴素,本文将要介绍的ggthemr包专门针对原 ...

  4. (数据科学学习手札44)在Keras中训练多层感知机

    一.简介 Keras是有着自主的一套前端控制语法,后端基于tensorflow和theano的深度学习框架,因为其搭建神经网络简单快捷明了的语法风格,可以帮助使用者更快捷的搭建自己的神经网络,堪称深度 ...

  5. (数据科学学习手札42)folium进阶内容介绍

    一.简介 在上一篇(数据科学学习手札41)中我们了解了folium的基础内容,实际上folium在地理信息可视化上的真正过人之处在于其绘制图像的高度可定制化上,本文就将基于folium官方文档中的一些 ...

  6. (数据科学学习手札40)tensorflow实现LSTM时间序列预测

    一.简介 上一篇中我们较为详细地铺垫了关于RNN及其变种LSTM的一些基本知识,也提到了LSTM在时间序列预测上优越的性能,本篇就将对如何利用tensorflow,在实际时间序列预测任务中搭建模型来完 ...

  7. (数据科学学习手札32)Python中re模块的详细介绍

    一.简介 关于正则表达式,我在前一篇(数据科学学习手札31)中已经做了详细介绍,本篇将对Python中自带模块re的常用功能进行总结: re作为Python中专为正则表达式相关功能做出支持的模块,提供 ...

  8. (数据科学学习手札69)详解pandas中的map、apply、applymap、groupby、agg

    *从本篇开始所有文章的数据和代码都已上传至我的github仓库:https://github.com/CNFeffery/DataScienceStudyNotes 一.简介 pandas提供了很多方 ...

  9. (数据科学学习手札61)xpath进阶用法

    一.简介 xpath作为对网页.对xml文件进行定位的工具,速度快,语法简洁明了,在网络爬虫解析内容的过程中起到很大的作用,除了xpath的基础用法之外(可参考我之前写的(数据科学学习手札50)基于P ...

随机推荐

  1. Vim中增加ga键的vmap功能

    ga是Vim自带的显示光标字符编码的功能,但是反过来,没有从编码显示对应字符的功能. 因为编码是多位数,所以可视模式下写了此功能. 规则: 纯数字认为是10进制 其他情况都认为是16进制 纯数字的话, ...

  2. Linux--sudo权限讲解

    sudo简介:sudo是linux系统管理指令,是允许系统管理员让普通用户执行一些或者全部的root命令的一个工具,如halt,reboot,su等等.这样不仅减少了root用户的登录 和管理时间,同 ...

  3. 文本处理三剑客之 Sed ——高级编辑命令

    本篇介绍sed的高级编辑命令 高级编辑命令 P:打印模式空间开端至\n内容,并追加到默认输出之前 n: 读取匹配到的行的下一行覆盖至模式空间 N:读取匹配到的行的下一行追加至模式空间 h: 把模式空间 ...

  4. Lovable eccentric

    It took him four years to stage this elaborate joke simply to prove that critics do not always know ...

  5. Ace admin 如何实现类似于freamset加载页面

    如上标题所述,ace admin做后台页面的时候,可以实现类似于用freamset的功能,但是ace admin做的比freamset更好,他可以用异步加载的形式展示,而加载的页面的内容可以尽可能的少 ...

  6. UVa 12186 - Another Crisis(树形DP)

    链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  7. 手绘web原型设计的感受

    当下有许多流行的Web原型设计工具,比如mockplus等,mockplus在我们团队初次开发rms系统用到过,确实还不错,但是,原型工具有其优势也有其劣势. 礼拜一开会时,经理跟我说,觉得现在的LM ...

  8. vue路由页面加载的几种方法~

    懒加载 (1)定义:懒加载也叫延迟加载,即在需要的时候进行加载,随用随载. (2)为什么需要懒加载: 在单页应用中,如果没有应用懒加载,运用webpack打包后的文件将会异常的大,造成进入首页时,需要 ...

  9. uiwebview与objective-c

    利用oc调用js很简单, 系统直接提供了方法stringByEvaluatingJavaScriptFromString [webView stringByEvaluatingJavaScriptFr ...

  10. 『ACM C++』 Codeforces | 1066B - Heaters

    今日不写日感,直接扔上今日兴趣点: 新研究称火星曾经有一个巨大的地下水系统 链接:https://mbd.baidu.com/newspage/data/landingsuper?context=%7 ...