新規Railsプロジェクトの作成手順のメモ

$ mkdir project_name
$ cd project_name
$ bundle init
$ echo "gem 'rails'" >> Gemfile
$ bundle install --path vendor/bundle --jobs=4
$ bundle exec rails new . -B -d mysql --skip-turbolinks --skip-test --api
# -B: bundle installを行わないようにする
# DB はmysqlを使用
# turbolinks オフ
# minitestを使わない
# API モード

参考

rails new

.gitignore

linuxのサーバでcronでコマンドを定期実行する

  • cron は決められた時間にコマンドを実行するデーモン(Unix系のOSで、主にバックグラウンドで動作するプロセス)
    • ユーザーが直接コマンドをプロンプトに入力しなくても希望の時間に特定のコマンドを実行するための仕組み
    • cronはデーモンとしてシステム起動時に立ち上がる
    • /etc/crontab. /etc/cron.d/*, /var/spool/crontab/*cron jobと呼ぶコマンドを羅列したファイルを読み込み指定された時間に実行する
$ vim /etc/crontab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/

# For details see man 4 crontabs

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name command to be executed
$ ll /etc/cron.d
-rw-r--r-- 1 root root 113 Sep 29  2016 0hourly
-rw-r--r-- 1 root root 108 Sep 18  2014 raid-check
-rw-r--r-- 1 root root 176 Nov  1  2014 update-motd
* cronのプロセスは以下で確認
$ ps ax | grep cro[n]
 2647 ?        Ss     0:00 crond

For CentOS

$ service crond status
crond (pid  2647) is running...

For Ubuntu

$ service cron status

毎日深夜AM4:00にrootユーザでunix コマンドを実行する場合は以下の2つの方法どちらかで設定できる

$ sudo vim /etc/crontab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/

# For details see man 4 crontabs

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name command to be executed
0 4 * * * root touch /hoge.md

OR

$ sudo su root
# crontab -l
no crontab for root
# crontab -e
0 4 * * * touch /hoge.md
$ crontab -l
0 4 * * * touch /hoge.md

reference from

Trello APIで特定のboardのlabelを削除する

背景

trello のボードを整理したくて、labelを削除しようと思ったけど、量が多すぎて萎えて、scriptでやろうと思った

コード

require 'trello'
require 'dotenv'

Dotenv.load
Trello.configure do |config|
  config.consumer_key = ENV['TRELLO_CONSUMER_KEY']
  config.consumer_secret = ENV['TRELLO_CONSUMER_SECRET']
  config.oauth_token = ENV['TRELLO_OAUTH_TOKEN']
end

#  hogeというボードのurl( https://trello.com/b/qWsxtqhF/hoge ) の qWsxtqhF の部分がboard id
BOARD_ID = "qWsxtqhF"

board = Trello::Board.find(BOARD_ID)
label_ids = board.labels.map(&:id)

label_ids.each do |id|
  label = Trello::Label.find(id)
  label.delete
  puts "delete label #{id} done!"
end

dotenvの使い方についてはこちら

qiita.com

認証まわりについてはこちら

qiita.com

所感

reference from

Swift ざっくり文法 (4)

  • Class
import Foundation

class Myclass {
    let msg:String
    let name:String?
    
    init(msg:String = "hello") {
        self.msg = msg
        self.name = nil
    }
    
    init(msg:String = "hello", name:String) {
        self.msg = msg
        self.name = name
    }
    
    func hello() {
        var helloMsg:String
        if let user = name {
            helloMsg = user + "san" + msg
        } else {
            helloMsg = msg
        }
        print(helloMsg)
    }
}
import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        let myObj = Myclass()
        myObj.hello() // hello
        let myObjWithMsg = Myclass(msg: "good night")
        myObjWithMsg.hello() // good night
        let myObjWithName = Myclass(name: "Alex")
        myObjWithName.hello() // Alex、hello
        let myObjWithMsgAndName = Myclass(msg: "good night", name: "Alex")
        myObjWithMsgAndName.hello() // Alex、good night
    }
---
}
  • Convenience initializer
class Myclass {
    let msg:String
    let name:String?

-    init(msg:String = "hello") {
-        self.msg = msg
-        self.name = nil
-    }

-    init(msg:String = "hello", name:String) {
+    init(msg:String, name:String) {
        self.msg = msg
        self.name = name
    }
    
+    convenience init (msg:String = "hello") {
+        self.init(msg: msg, name: "Anonymous")
+    }    
}
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        let myObj = Myclass()
-        myObj.hello() // hello
+        myObj.hello() // Anonymous, hello
        let myObjWithMsg = Myclass(msg: "good night")
-        myObjWithMsg.hello() // good night
+        myObjWithMsg.hello() // Anonymous,  good night
-        let myObjWithName = Myclass(name: "Alex")
-        myObjWithName.hello() // Alex、hello
        let myObjWithMsgAndName = Myclass(msg: "good night", name: "Alex")
        myObjWithMsgAndName.hello() // Alex、good night
    }
}

convenience initializerを使うと、複数のinitializerがあるときに、別のinitializerを呼ぶことができる。

  • stored property と、computed property
    • stored propertyは、定数・変数で定義される
    • computed propertyは、関数を介して値をやり取りする。値を保持しておらず、設定値を内部的に宣言しておいた定数や変数に設定して保管する
class Circle {
    var radius:Double = 1.0 // stored property
    var area:Double { // computed property
        get{ // property への参照
            return radius * radius * Double.pi
        }
        set(meseki){ // property への値の設定
            radius = sqrt(meseki / Double.pi)
        }
    }
}

let myCicle = Circle()
print("\(myCicle.radius)") // 1.0
print("\(myCicle.area)") // 3.14159265358979
myCicle.area *= 2
print("\(myCicle.radius)") // 1.4142135623731
print("\(myCicle.area)") // 6.28318530717959
myCicle.radius = 3.0
print("\(myCicle.radius)") // 3.0
print("\(myCicle.area)") // 28.2743338823081

read only の property

class Circle {
    var radius:Double = 1.0
    var area:Double {
        get{
            return radius * radius * Double.pi
        }
-        set(meseki){
-            radius = sqrt(meseki / Double.pi)
-        }
    }
}

let myCicle = Circle()
myCicle.radius = 3.0
print("\(myCicle.radius)") // 3.0
print("\(myCicle.area)") // 28.2743338823081

+ myCicle.area = 300 // error: cannot assign to property: 'area' is a get-only property

Read onlyであれば以下のようにも書ける

class Circle {
    var radius:Double = 1.0
    var area:Double {
-        get{
            return radius * radius * Double.pi
-        }
    }
}
  • property observer ( propertyに値がsetされたことをwillSet, didSetで知ることができる )
    • willSetは値が更新される直前に呼ばれ、新しくsetされる値に newValue でアクセスできる
    • didSetは値が更新された直後に呼ばれ、更新前の値に oldValue でアクセスできる
class Player {
    var times = 0
    var level:Int {
        willSet {
            print("------")
            print("willSet \(newValue)")
        }
        
        didSet {
            if oldValue != level {
                times += 1
                print("\(times) update\n\(oldValue) -> \(level)")
            } else {
                print("no changes")
            }
        }
    }
    
    init () {
        level = 0
    }
}

var thePlayer = Player()
thePlayer.level = 10
thePlayer.level = 10
thePlayer.level = 20

// ------
// willSet 10
// 1 update
// 0 -> 10
// ------
// willSet 10
// no changes
// ------
// willSet 20
// 2 update
// 10 -> 20
  • Class property
class Car {
    static var count = 0
    var moving = false
    
    func start() {
        Car.count += 1
        moving = true
    }
    
    func stop() {
        if Car.count > 0 {
            Car.count -= 1
            moving = false
        }
    }
}

let car1 = Car()
let car2 = Car()
print("\(Car.count)") // 0
car1.start()
car2.start()
print("\(Car.count)") // 2
car2.stop()
print("\(Car.count)") // 1
  • Computed class propety
class MyClass {
    static var radian:Double = 0.0
    class var degree:Double {
        get {
            return radian * 90/Double.pi
        }
        
        set(dosu){
            radian = dosu * Double.pi/90
        }
    }
}

MyClass.degree = 18
let katamuki = MyClass.degree
print("\(katamuki)") // 18.0

MyClass.radian = Double.pi/2
let katamuki2 = MyClass.degree
print("\(katamuki2)") // 45.0
  • Class method
class Message {
    class func hello() -> String {
        return "hello"
    }
}

let msg = Message.hello()
print(msg)
  • Access Right
    • access rightを省略するとinternalになる。
    • class がfileprivateだと、property/methodをinternalにすることはできない。
    • fileprivate(set) だとfile外からは、read onlyになる
access right ---
open ---
public Inheritanceとoverrideができない。
internal module外からアクセスできない
fileprivate ファイル外からアクセスできない
private class外からアクセスできない
  • Extension
class Player {
    var name:String = ""
    func hello() {
        print("やあ!" + name)
    }
}

extension Player {
    var who:String {
        get {
            return name
        }
        set(value) {
            name = value
        }
    }
    
    func bye() {
        print("good bye " + name)
    }
}

let obj = Player()
obj.who = "sam" // やあ!sam
obj.hello()
obj.bye() // good bye sam
  • Inheritance
    • A classを継承したB classを作成する。
      • A class は、B classのsuperclass
      • B class は、A classのsubclass
      • B class -> A class
      • 1つのclassが直接継承できるclassは一個だけ
---
class ViewController: UIViewController {
---
}
  • Override
    • superclassと同名のメソッドをsubclass側でも定義してメソッドを上書きする
    • superは、superclassのインスタンス, selfは現在のインスタンス自身
override func viewDidLoad() { // superclass のviewDidLoad()を上書き
    super.viewDidLoad() // superclassのメソッドを実行
    // Do any additional setup after loading the view, typically from a nib.
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}
  • final ( 継承を禁止したいclass, override されては困るメソッドに付ける。 )
final class MyClass {
    func hello() {
        print("hello")
    }
}
class MyClass {
    final func hello() {
        print("hello")
    }
}
  • Protocol ( classが必ず実装しなければならないpropertyやmethodを指定した仕様書のようなもの。実装しないとエラーになる。 )
    • 読み書き可能なpropertyには、{get set} をつける
    • protocolは他のprotocolを継承できる
protocol GameProtocol {
    var gamePoint:Int {get}
    func hit()
    func miss()
}

- class MyGame:GameProtocol {
+ class MyGame:GameProtocol { // protocol requires function 'miss()' with type '() -> ()'; do you want to add a stub?
    private var total = 0
    var gamePoint: Int {
        return total
    }
    
    func hit() {
        total += 10
        print("hit! +10")
    }

-    func miss() {
-        total /= 2
-        print("you miss, half")
-    }    
+ //    func miss() {
+ //        total /= 2
+ //        print("you miss, half")
+ //    }
}

let myGameObj = MyGame()
myGameObj.hit() // hit! +10
print(myGameObj.gamePoint) // 10
myGameObj.miss() // you miss, half
print(myGameObj.gamePoint) // 5
myGameObj.hit() // hit! +10
print(myGameObj.gamePoint) // 15
  • Enumeration ( 複数の値を一つの型として宣言するために使用。Swiftの列挙型は値だけではなく、propertyやメソッドを持つことができる。)
enum MensSize {
    case S
    case M
    case L
    case XL
}

enum WomenSize {
    case XS, S, M, L
}

var mySize = MensSize.M
mySize = .S // 型推論で、mySizeは、MensSize型になる

var herSize:WomensSize
herSize = .XS

print(mySize) // S
print(herSize) // XS
enum Direction:Int {
    case forward = 1
    case backword // 2
    case right // 3
    case left  // 4
}

let muki1 = Direction.forward
let muki2 = Direction.backword
let muki3 = Direction.right
let muki4 = Direction.left

print(muki1.rawValue) // 1
print(muki2.rawValue) // 2
print(muki3.rawValue) // 3
print(muki4.rawValue) // 4
let muki5 = Direction(rawValue: 3)
if let muki = muki5 { // muki5はnilかもしれないので、Optional Bindingになっている。
    print(muki)
}
  • Enum で型を列挙する
enum Pattern {
    case Monotone(_:PColor)
    case Border(color1:PColor, color2:PColor)
    case Dots(base:PColor, dot1:PColor, dot2:PColor)

    enum PColor:String {
        case red = "red"
        case green = "緑"
        case yellow = "yellow"
        case white = "白"
    }
}

let shirt1 = Pattern.Monotone(.red)
let shirt2 = Pattern.Border(color1: .white, color2: .red)
let shirt3 = Pattern.Dots(base: .yellow, dot1: .white, dot2: .green)
  • Propertyを持ったEnum
enum Ticket {
    case Gold, A, B
    static var name = "入場券"
    
    var area:String {
        get {
            switch self {
            case .Gold:
                return "Gold sheet"
            case .A:
                return "A sheet"
            case .B:
                return "B sheet"
            }
        }
    }
    
    var price:Int {
        get {
            switch self {
            case .Gold:
                return 24000
            case .A:
                return 5000
            case .B:
                return 2000
            }
        }
    }
}

Ticket.name = "hoge live"
print(Ticket.name) // hoge live
let ticket = Ticket.A
print(ticket) // A
print(ticket.price) // 5000
print(ticket.area) // A sheet
  • Methodを持ったEnum
enum Signal:String {
    case Green = "green"
    case Red = "red"
    
    var color:String {
        return self.rawValue
    }
    
    static func description() -> String {
        return "red or green signal"
    }
    
    func isRun() -> Bool {
        if self == .Green {
            return true
        } else {
            return false
        }
    }
    
    mutating func turn() { // 自身を変更するメソッドには `mutating` をつける必要がある
        if self == .Green {
            self = .Red
        } else {
            self = .Green
        }
    }
}

let text = Signal.description()
print(text)  // red or green signal
var lamp = Signal.Green
print(lamp.color) // green
print(lamp.isRun()) // true
lamp.turn()
print(lamp.color) // red
print(lamp.isRun()) // false
  • Struct ( classと違って継承はできない )
struct Box {
    let width:Int
    let height:Int
    let size:String
    let tanka:Int
    var kosu:Int
    
    var price:Int {
        return tanka*kosu
    }
    
    init(width:Int, height:Int, tanka:Int, kosu:Int){
        self.width = width
        self.height = height
        self.tanka = tanka
        self.kosu = kosu
        
        if (width+height) < 250 {
            size = "M"
        } else {
            size = "L"
        }
    }
    
    func sellprice(nebiki:Int = 0) -> Int {
        return price - nebiki*kosu
    }
    
    mutating func discount(count: Int) {
        kosu -= count
    }
}

var box = Box(width: 120, height: 80, tanka: 700, kosu: 6)
print(box) // Box(width: 120, height: 80, size: "M", tanka: 700, kosu: 6)
let selling_price = box.sellprice(nebiki: 10)
print(selling_price) // 4140
box.discount(count: 5)
print(box) // Box(width: 120, height: 80, size: "M", tanka: 700, kosu: 1)
  • Structのcopy
    • Structはclassのobjectと違って、参照型ではなく、値型
    • つまりvariable aに入っているStructをvariable bに代入すると参照ではなく、値が複製されて新しいStructとして代入される
    • String, Array, DictionaryはStruct、だから参照型ではなく、値型
class BoxClass {
    var color:String = "red"
}

struct BoxStruct {
    var color:String = "red"
}

// class
let cBox1 = BoxClass()
let cBox2 = cBox1
cBox2.color = "green"

// struct
let sBox1 = BoxStruct()
var sBox2 = sBox1
sBox2.color = "green"

print("cbox1: \(cBox1.color)") // green
print("cbox2: \(cBox2.color)") // green
print("sbox1: \(sBox1.color)") // red
print("sbox2: \(sBox2.color)") // green
  • Structのsubscript

  • Struct, subscript

struct Stock {
    var name:String
    var data:[String:Int] = [:]
    init(name:String){
        self.name = name
    }
    
    subscript(color:String, size:Double) -> Int {
        get {
            let key = color + String(size)
            if let value = data[key] {
                return value
            } else {
                return 0
            }
        }
        
        set {
            let key = color + String(size)
            data[key] = newValue
        }
    }
}

var shoes = Stock(name: "Tiger")
shoes["green", 24.5] = 3
shoes["green", 25.0] = 5
shoes["red", 26.0] = 5

print(shoes.name) // Tiger
print(shoes["green", 24.5]) // 3
print(shoes["green", 25.0]) // 5
print(shoes["red", 26.0]) // 5

shoes["green", 24.5] -= 2
print(shoes["green", 24.5]) // 1

print(shoes["black", 24.5]) // 0
  • Structのprotocol
protocol Monster {
    var monsterName:String {get}
    var hp:Int {get set}
    mutating func updateHP(pt:Int)
}

struct Bokemon: Monster {
    private(set) var monsterName: String // propertyがread onlyなので、private(set)を付ける
    var hp: Int
    mutating func updateHP(pt: Int) {
        hp += pt
    }
}

var monster = Bokemon(monsterName: "swifty", hp: 200)
print(monster.monsterName) // swifty
print("HP \(monster.hp)") // 200
monster.updateHP(pt: 30)
print("HP \(monster.hp)") // 230

reference from

https://www.amazon.co.jp/dp/4800711843

Swift ざっくり文法 (3)

  • 関数定義
func dice() -> Int {
    let num = 1 + arc4random_uniform(6)
    return Int(num)
}
 // メソッド定義(戻り値がない関数をメソッドと呼ぶ)
func hello() {
    print("hello")
}

or

func hello() -> Void {
    print("hello")
}
  • guard-else ( 条件を満たさないときに実行される )
func half(num: Double){
-    if (num < 10) {
+    guard num>=10 else {
        return
    }
    let halfNum = num/2
    print("\(num)の半分は\(halfNum)")
}

half(num: 25) // 25.0の半分は12.5
half(num: 9)
half(num: 12) // 12.0の半分は6.0
  • defer statement ( 処理(ブロック)を抜ける前にかならず実行する )
func half(num: Double){
+    defer {
+        print("計算終了")
+    }
    guard num>=10 else {
        return
    }
    let halfNum = num/2
    print("\(num)の半分は\(halfNum)")
}

half(num: 25)
// 25.0の半分は12.5
// 計算終了  
half(num: 9)
// 計算終了 <- half(num: 9)は中断されるが、defer文で書いているので実行される 
half(num: 12)
// 12.0の半分は6.0
// 計算終了
  • 可変長引数
func sum(numbers: Double...) -> Double {
    var total: Double = 0.0
    for num in numbers {
        total += num
    }
    return total
}

print(sum(numbers: 4, 5, 6, 7))
  • default引数
- func pricel(ninzu: Int, tanaka: Int) -> Int {
+ func pricel(ninzu: Int = 1, tanaka: Int = 250) -> Int { 
    let result = tanaka * ninzu
    return result
}

print(pricel(ninzu: 3, tanaka: 1300))
  • Tupleを利用した複数の戻り値
- func pricel(ninzu: Int, tanaka: Int) -> Int {
+ func pricel(ninzu: Int, tanaka: Int, rate: Double) -> (hoge: Int, fuga: Double) {
    let result = tanaka * ninzu
+    let updatedResult = Double(result) * rate
-    return result
+    return (result, updatedResult)
}

- print(pricel(ninzu: 3, tanaka: 1300))
+ print(pricel(ninzu: 3, tanaka: 1300, rate: 1.8).hoge)
  • 関数の多重定義( 同名の関数でも引数名や引数の個数が違うと別の関数として扱われる。)
func calc(a: Int, b: Int) -> Int {
    return a+b
}

func calc (c: Int, d: Int) -> Int {
    return c*d
}

func calc(a: Int, b: Int, c: Int) -> Int {
    return (a+b)*c
}

print(calc(a: 2, b: 3)) // 5
print(calc(c: 2, d: 3)) // 6
print(calc(a: 2, b: 3, c: 4)) // 20
  • 外部引数名
- func pricel(ninzu: Int, tanaka: Int) -> Int {
+ func pricel(hoge ninzu: Int, fuga tanaka: Int) -> Int {
    let result = tanaka * ninzu
    return result
}

- print(pricel(ninzu: 3, tanaka: 1300))
+ print(pricel(hoge: 3, fuga: 1300))
  • 引数名なし
- func pricel(hoge ninzu: Int, fuga tanaka: Int) -> Int {
+ func pricel(_ ninzu: Int, _ tanaka: Int) -> Int {
    let result = tanaka * ninzu
    return result
}

- print(pricel(ninzu: 3, tanaka: 1300))
+ print(pricel(3, 1300))

reference from

https://www.amazon.co.jp/dp/4800711843

Swift ざっくり文法 (2)

  • Tuple ( タプル )
let product: (String, Int) = ("Swift", 2015)
let kingaku = (1000, 80) // 型推論で(Int, Int)に決まる
kingaku = (1060,  "hoge") // error: cannot call value of non-function type '(Int, Int)'
let data = (1000, 80)
let (price, _) = data
print(price)

不要な値は、_ で無視できる。

let data = (1000, 80)
print(data.0)

indexでaccess

let kingaku = (price: 1000, tax: 80)
let seikyuugaku = kingaku.price + kingaku.tax
print(seikyuugaku)

ラベル付け

  • Range

    • ..< 終了値を含まない
    • ... 終了値を含む
  • Bitwise Operators

    • 2進数 接頭辞に 0b
    • 16進数 接頭辞に 0x

    • Bit Shift

      • 指定した方向に桁をシフトする演算( 10進数の数値を左を一桁シフトすると値が10倍になるように2進数の値を左へ1桁シフトすると値が2倍になる。 )
let v: UInt8 = 0b00000101
let v2 = v<<1
print(v, v2) // 5, 10
  • Bitwise operation
演算式 説明
a & b ビット積、各桁を比較し、両方の桁が1ならば1
a b | ビット和、各桁を比較し、どちらかの桁が1ならば1
a ^ b 排他的ビット和、各桁を比較し、片方が1の桁だけ1
~a ビット否定、各桁の1と0を反転

16進数#40E0D0 からビット積とビットシフトを使って、RGBを取り出して、0~255 の値に変換し、さらに255 で割って0~1にしてビューの背景色に指定

    let RGB: UInt32 = 0x40E0D0 // turquoise(64, 224, 208)
    let red = (RGB & 0xFF0000) >> 16 // 上位二桁
    let green = (RGB & 0x00FF00) >> 16 // 中央二桁
    let blue = RGB & 0x0000FF // 下二桁
    
    let R = CGFloat(red)/255
    let G = CGFloat(green)/255
    let B = CGFloat(blue)/255
    view.backgroundColor = UIColor(red: R, green: G, blue: B, alpha: 1)

ビット否定

let v: UInt8 = 0b00001010
let v2 = ~v
print(v, v2) //10 245
  • if statementでは以下のような書き方が可能
- if ((sugaku>=40) && (eigo>=60) && ((suugaku+eigo)>=120)) {
+ if sugaku>=40, eigo>=60, (suugaku+eigo)>=120 {
  • Switch statement
    • swiftのswitch statementは、breakがなくても抜けてくれる。
    • 意図的に処理を次のcase文に渡したい場合は、fallthrough キーワードを書く。

    • value binding

let size = (4, 10)
switch size {
    case (0, 0):
        print("hoge")
    case (5...10, 5...10):
        print("bar")
    case (5...10, let height): //
        print("height:" + "\(height)")
    case (let width, 5...10):
        print("width:" + "\(width)")
    default:
        print("foo")
}

where で、値の振り分けに条件式を使えるようになる。

let size = (45, 40, 100)
switch size {
    case let (width, height, _) where (width>=60) || (height>=60):
        print("hoge")
    case let (_, _, weight) where (weight>=80):
        print("bar")
default:
    print("foo")
}

caseに当てはまらない値があり得る場合には、最後のdefaultは必ず必要だが、caseに当てはまらない値がない場合はdefaultを省略可能

let aPoint = (50, 100)
switch aPoint {
    case (0, 0):
        print("中心点")
    case (0, _):
        print("x軸上の点")
    case (_, 0): //
        print("y軸上の点")
    case (x, y):
        print("点(\(x), \(y))")
}
  • 単に処理を任意の回数繰り返したい時( rubyでいうところの、timesみたいな感じ )
for _ in 1...15 {
    let num = arc4random_uniform(100)
    print(num, terminator:  ",")
}
  • for-in でstringから一文字ずつ取り出す
let message = "ありがとう"
for char in message {
    print(char)
}
// あ
// り
// が
// と
// う
  • 飛び飛びで繰り返す for-in stride()
for num in stride(from: 10, to: 30, by: 3) {
    print(num, terminator: ",")
}
// 10, 13, 16, 19, 22, 25, 28
  • 他の言語で言うところのdo-while は、swiftだとrepeat-while
  • loop ( for-in, while, repeat-while ) には、labelが付けられる
xloop: for x in 0...3 {
    yloop: for y in 0...3 {
        if (x<y) {
            print("------")
            continue xloop // yloopを中断して、xloopに抜ける
        }
        print((x, y))
    }
}
let vlist:Array = [[4, 2], [5], [9, 8, 10], [6, 8, -9], [4, 2], [9, 3]]
outloop: for alist in vlist {
    inloop: for v in alist {
        if v<0 {
            print(alist)
            break outloop // inloop だけでなく、outloopも中断する。
        }
    }
}
  • 複数行のString literal ( swift4から )
"""
swift4
swift3
swift4
"""
  • Array
let colors:[String] = ["red", "blue", "green"]
let hoge:[Any] = ["ed", "bl", 3]
var numList:Array<Int> = [12, 34, 56, 79, 59]
var resultList:Array<Bool>
resultList = [true, false, true, false]

型推論

var stringList = ["foo", "bar", "baz"]
// stringList は、型推論で[String]に設定されているため、それ以外の型を入れようとするとエラー
stringList = [3, 4, 6] // error: cannot convert value of type 'Int' to expected element type 'String'

空のArray

var resultList:Array<Bool>
resultList = []
var resultList = [Bool]()
var resultList = Array<Double>()

Repeating

var stars = String(repeating: "★", count: 7) // "★★★★★★★"
var resultList = Array<Bool>(repeating: true, count: 5) // [true, true, true, true, true]

配列を別の変数に代入すると、変数には配列の参照ではなく、コピー(複製)が作られて入る。

var array1 = [1, 2, 3]
let array2 = array1
// ここまではシャローコピー
array1[0] = 99
// ここでディープコピー
print("array \(array1)")
print("array \(array2)")
  • Copyの種類

    • Shallow Copy
      • 元の配列の参照をコピーしただけで実際には同じ配列を指した別名の配列を作る
    • Deep copy
      • 同じ値をもった完全に新しい別の配列を作る
    • Lazy copy in Swift
      • 配列を一旦Shallow Copyして、配列の要素や値を変更しようとした時点で自動的にDeep copyした新しい配列を作る
  • Set

    • 配列と違ってSetは同じ値を重複して持つことができず、値には順番がない。
let colorSet:Set<String> = ["red", "green", "blue", "green"]
print(colorSet) // ["green", "red", "blue"]
print(type(of: colorSet)) // Set<String>

Array -> Set, Set -> Array

var colorArray = ["red", "green", "blue", "green"]
print(colorArray, type(of: colorArray)) // ["red", "green", "blue", "green"] Array<String>
let colorSet = Set(colorArray)
colorArray = Array(colorSet)
print(colorSet, type(of: colorSet)) // ["blue", "green", "red"] Set<String>
print(colorArray, type(of: colorArray)) // ["blue", "green", "red"] Array<String>
  • 空のSet
var numSet:Set<Int> = []
  • Setに値を追加しても、重複していれば、同じ値は入らない。
var numSet:Set<Int> = []
numSet.insert(3)
numSet.insert(5)
numSet.insert(7)
numSet.insert(9)
numSet.insert(5)
print(numSet) // [5, 7, 3, 9]
  • Closure
let ageArray = [21, 30, 28, 35, 45, 52, 33]
let age30to39 = ageArray.filter({(age: Int) -> Bool in
    return (age>=30)&&(age<40)
})
print(age30to39)
  • dictionary
    • キーは、全てが同じ型で重複しない一意なものでないといけない。
let sizeTable = ["S": 47, "M": 52, "L": 55]
let sizeTable:[String:Int] = ["S": 47, "M": 52, "L": 55]
let sizeTable:Dictionary<String, Int> = ["S": 47, "M": 52, "L": 55]

空のdictionary

let sizeTable:[String:Int] = [:]
let sizeTable = [String:Int]()
let sizeTable = Dictionary<String, Int>()

TupleからDictionaryを作る

let a = ("A", 1)
let b = ("B", 2)
let c = ("C", 3)
let abcDic = Dictionary(dictionaryLiteral: a, b, c)
print(abcDic)

reference from

https://www.amazon.co.jp/dp/4800711843