스위프트에서 Closures는 다른 언어에서의 Lambda와 비슷하다.

let closuresTest:(Int) -> (String) = { _ in
    
    return "Hello, Polytech!"
}

let result = closuresTest(0)
print(result)

결과 : Hello, Polytech!

 

이유는 모르겠지만... 인풋 없이 하고 싶은데 계속 에러가 난다... 이런식으로라도 그냥 의미 없게라도 넣어야 작동한다...

let closuresTest:(Bool) -> (String) = { _ in
    
    return "Hello, Polytech!"
}

let result = closuresTest(false)	// () 안의 값은 아무 의미도 없다... 그냥 arguments를 지정하지 않을 경우 누락되었다고 에러가 발생해서 형식상 넣어준 것이다.
print(result)

결과 : Hello, Polytech!

sort에 closures를 적용시켜보자.

 

Swift의 내장 함수 sort는 기본적으로 오름차순 정렬만 된다. 내림차순을 하려면 어떻게 해야할까?

 

1. sort 후 reverse 하기

var testArray:Array<Int> = [4, 6, 8, 1, 3]
print(testArray)

결과 : [4, 6, 8, 1, 3]


var testArray = [4, 6, 8, 1, 3]
testArray.sort()

print(testArray)

결과 : [1, 3, 4, 6, 8]


var testArray = [4, 6, 8, 1, 3]
testArray.sort()
testArray.reverse()

print(testArray)

결과 : [8, 6, 4, 3, 1]

하지만 이렇게 정렬하는 것은 불필요한 코드가 생기고 불필요한 계산이 추가된다.

 

2. 정렬을 내가 정의한 함수의 알고리즘으로 작동시키기

insertion sort는 배열에서 2개의 숫자를 비교한 뒤 Boolean 값이 True인 것만 반환하여 정렬한다.

 즉, 기본이 오름차순 정렬인 스위프트에서 정렬을 시작하면, 배열의 index 0, index 1 2개의 값이 sort 함수로 들어가고, 그 sort 함수는 이 2개의 값을 비교한다.
 [5, 3, 7] 이라는 배열이 있다. 이 때 index 0의 값을 잠시 number1이라 하자. 마찬가지로, index 1의 값을 잠시 number2라 하자.
그러면 number1(=5) > number2(=3)이기 때문에 return 값으로 number1 < number2를 반환하고 싶지만 결과가 false가 된다.
 따라서 이번에는 다시 두 수의 순서를 바꾸어 비교를 해본다. 그러면 number(=3) < number2(=5) 이므로 true가 된다. 따라서, index 0과 index 1은 순서가 바뀌게 된다. 즉, 이제 [3, 5, 7]이 된거다.
 그러면 또 다시 index 0과 index 1이 뒤바뀐 [3, 5, 7]을 가지고 비교를 한다. 이번에는 새 index 1의 값을 잠시 number1이라 하고, index 2의 값을 잠시 number2라 하자. 그러면 number1(=5) < number2(=7)이기 때문에 return 값으로 number1 < number가 바로 true가 되고 이를 그대로 반환한다. 즉, 최종적으로 [3, 5, 7]로 정렬이 되는 것이다. 배열의 길이가 짧든 길든 이런 과정을 배열의 마지막까지 반복해서 정렬을 한다.

따라서, 이 때 sort가 반환하는 return되는 Bool 값의 True 값을 바꾸면 Ascending Sort를 Descending Sort로 바꿀 수 있는 것이다. 따라서 함수는 (Int, Int) -> Bool 형식이 되어야 한다.

func sortASC(num1: Int, num2: Int) -> Bool {
   return num1 < num2
}

즉, 이런 형태의 Bool 로직을 반대로 바꿔주면 된다.

func sortDESC(num1: Int, num2: Int) -> Bool {
   return num1 > num2
}

해설 : 앞에 오는 숫자가 뒤에 오는 숫자보다 더 크면 true고 이를 return하라는 것이다. 즉, 큰수 -> 작은수 순으로 정렬된다.

 

그리고 sort의 Bool판단 로직을 내가 정의한 함수로 작동시킨다.

var numbers = [4, 6, 8, 1, 3]

func sortDESC(num1: Int, num2: Int) -> Bool {
   return num1 > num2
}

numbers.sort(by: sortDESC)

결과 : [8, 6, 4, 3, 1]

 

마찬가지로 문자열 정렬일 경우는 (String, String) -> Bool 형식이 되어야 한다.

var name = ["Bella", "Elin", "Matilda", "Raina", "Kate", "Alice"]

func sortDESC(s1: String, s2: String) -> Bool {
    return s1 > s2
}
name.sort(by: sortDESC(s1:s2:))

결과 : ["Raina", "Matilda", "Kate", "Elin", "Bella", "Alice"]

 

3. Closures 익명함수를 써서 위 코드를 줄여보자.

다른 언어에서 Lambda와 비슷한 역할을 하는 것이 스위프트에서는 Closures라는 것이 있다.

func sortDESC(num1: Int, num2: Int) -> Bool {
   return num1 > num2
}

// 에서 함수의 이름을 지우고 함수 전체를 {}로 감싼다.
// 즉, 함수 이름을 지운 다음 그 자리(num1: Int 앞부분)에 { 를 입력하고
// 함수 전체를 {}로 감쌌기 때문에 Bool 뒤에 따로 함수의 로직만 분리해두었던 { 의 시작 부분은 in으로 바꿔준다.
// 최종 형태는 다음과 같다.

{(num1: Int, num2: Int) -> Bool in
   return num1 > num2
}

// 이제 이것을 함수의 이름을 넣었던 자리에 익명으로 함수 자체를 넣어버리자. 따라서

numbers.sort(by: sortDESC)

// 는 이제 이렇게 바꿔 쓸 수 있다.

numbers.sort(by: {(num1: Int, num2: Int) -> Bool in
   return num1 > num2
})

결과 : [8, 6, 4, 3, 1]

 

4. 위 익명함수를 줄여보자. (Closures 간략하게 줄이기)

스위프트에서는 인풋 파라미터의 자료형을 명확히 지정하지 않아도 스스로 유추가 가능하다. 따라서 위 로직은 더 짧게 바꿀 수 있다. 아예 num1, num2도 n1, n2로 줄여보자.

var numbers = [4, 6, 8, 1, 3]

numbers.sort(by: {n1, n2 -> Bool in return n1 > n2})
print(numbers)

결과 : [8, 6, 4, 3, 1]

 

5. 이 익명함수를 더 줄요보자. (Closuers 더 간략하게 줄이기)

스위프트의 closures는 파라미터를 $0, $1, $2, ... 로 축약할 수 있다. 따라서 위 코드는 다음과 같이 줄일 수 있다. 심지어 위에서는 자료형을 생략했지만 이제 인풋 파라미터를 명시하는 것 조차 생략할 수 있다.

var numbers = [4, 6, 8, 1, 3]

numbers.sort(by: {$0 > $1})
print(numbers)

결과 : [8, 6, 4, 3, 1]

 

 

 

더보기

cf. 정렬을 삼항 연산자와 Closures를 사용하기(오름차순)

data.sort (by: {sortedColumn.sorting == .ascending ? $0[sortedColumn.column] < $1[sortedColumn.column] : $0[sortedColumn.column] > $1[sortedColumn.column]})

위 수식을 아래와 같이 사용할 수도 있다.

data.sort {
  let ascending = $0[sortedColumn.column] < $1[sortedColumn.column]
  return sortedColumn.sorting == .ascending ? ascending : !ascending  // ? true -> 위에 let ascending : false -> ! 붙어서 < 가 반대로 뒤집혀 > 가 되니 descending으로 작동
}

 

 

 

 

 

사실... 파라미터 축약 마저도 생략하고 써도 내장함수에 정의되어 있어서 정렬된다...

var numbers = [4, 6, 8, 1, 3]

numbers.sort()          // 결과 : [1, 3, 4, 6, 8], inplace=true
numbers.sort(by: <)     // 결과 : [1, 3, 4, 6, 8], inplace=true
numbers.sort(by: >)     // 결과 : [8, 6, 4, 3, 1], inplace=true

numbers.sorted()        // 결과 : [1, 3, 4, 6, 8], inplace=false
numbers.sorted(by: <)   // 결과 : [1, 3, 4, 6, 8], inplace=false
numbers.sorted(by: >)   // 결과 : [8, 6, 4, 3, 1], inplace=false

 

 

var a:Int = 1
var test:Bool = a == 1 ? true : false
// var test:Bool = (a == 1) ? true : false 괄호를 생략하지 않으면 가독성이 더 좋다.

결과 : true

 

 

즉, 삼항 연산자는 변수 선언 + if ~ else 구문 2가지를 한 줄로 쓸 수 있는 간편한 방법이다.

 

var num1:Int = 10
var num2:Int = 12

var largeNum:Int
if num1 > num2 {
    largeNum = num1
} else {
    largeNum = num2
}
print(largeNum)

결과 : 12

 

이것을 삼항 연산자로 바꾸면

var num1:Int = 10
var num2:Int = 12

var largeNum:Int = num1 > num2 ? num1 : num2
print(largeNum)

결과 : 12

 

 

 

조건의 결과가 3가지인 경우도 가능하다.

var height:Int = 165

var message:String
if height >= 170 {
    message = "키가 170 이상입니다."
} else if height < 160 {
    message = "키가 160 미만입니다."
} else {
    message = "키가 160 이상, 170 미만입니다."
}

print(message)

결과 : 키가 160 이상, 170 미만입니다.

 

이것을 삼항 연산자로 바꾸면

var height:Int = 165

var message:String = height >= 160 ? height >= 170 ? "키가 170 이상입니다." : "키가 160 이상, 170 미만입니다." : "키가 160 미만입니다."

print(message)

결과 : 키가 160 이상, 170 미만입니다.

 

 

위 삼항 연산자의 경우 그 위에 있는 if ~ else if ~ else 와는 알고리즘이 다르다... true(true, false), false 로직이다... 만약 이것을 if ~ else 구문으로 동일하게 바꾸면 아래와 같다.

var height:Int = 165

var message:String
if height >= 160 {
    if height >= 170 {
        message = "키가 170 이상입니다."
    } else {
        message = "키가 160 이상, 170 미만입니다."
    }
} else {
    message = "키가 160 미만입니다."
}

print(message)

 

 

 

AWS 가입하고 띄우는 것을 배웠다. 가입에 문제가 발생해 실제로 띄워보지는 못 했고 교수님이 화면 녹화해주시는 것을 보며 배웠다.

그리고 하이퍼렛저 페브릭 다른 예제를 했고 도커 compose를 했다.

'개발자 > TIL' 카테고리의 다른 글

TIL 20.06.23  (0) 2020.06.23
TIL 20.06.22  (0) 2020.06.22
TIL 20.06.18  (0) 2020.06.20
TIL 20.06.17  (0) 2020.06.18
TIL 20.06.16  (0) 2020.06.18

자바스크립트 시간에 테이블 태그를 다시 배웠다. 그리고 구글 차트를 가져와 사용하는 것을 배웠다.

'개발자 > TIL' 카테고리의 다른 글

TIL 20.06.22  (0) 2020.06.22
TIL 20.06.19  (0) 2020.06.20
TIL 20.06.17  (0) 2020.06.18
TIL 20.06.16  (0) 2020.06.18
TIL 20.06.15  (0) 2020.06.16

Google Charts -> Line Charts -> 'Multiple line types' -> 'Code it yourself on JSFiddle'

 

HTML 을 복사해 아톰에 가서 <body> </body> 안에 붙여넣기 한다. (원본 소스)

  <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
  <div id="chart_div"></div>

 

JavaScript 를 복사해 아톰에 가서 <script> </script> 안에 붙여넣기 한다. (원본 소스)

google.charts.load('current', {packages: ['corechart', 'line']});
google.charts.setOnLoadCallback(drawCurveTypes);

function drawCurveTypes() {
      var data = new google.visualization.DataTable();
      data.addColumn('number', 'X');
      data.addColumn('number', 'Dogs');
      data.addColumn('number', 'Cats');

      data.addRows([
        [0, 0, 0],    [1, 10, 5],   [2, 23, 15],  [3, 17, 9],   [4, 18, 10],  [5, 9, 5],
        [6, 11, 3],   [7, 27, 19],  [8, 33, 25],  [9, 40, 32],  [10, 32, 24], [11, 35, 27],
        [12, 30, 22], [13, 40, 32], [14, 42, 34], [15, 47, 39], [16, 44, 36], [17, 48, 40],
        [18, 52, 44], [19, 54, 46], [20, 42, 34], [21, 55, 47], [22, 56, 48], [23, 57, 49],
        [24, 60, 52], [25, 50, 42], [26, 52, 44], [27, 51, 43], [28, 49, 41], [29, 53, 45],
        [30, 55, 47], [31, 60, 52], [32, 61, 53], [33, 59, 51], [34, 62, 54], [35, 65, 57],
        [36, 62, 54], [37, 58, 50], [38, 55, 47], [39, 61, 53], [40, 64, 56], [41, 65, 57],
        [42, 63, 55], [43, 66, 58], [44, 67, 59], [45, 69, 61], [46, 69, 61], [47, 70, 62],
        [48, 72, 64], [49, 68, 60], [50, 66, 58], [51, 65, 57], [52, 67, 59], [53, 70, 62],
        [54, 71, 63], [55, 72, 64], [56, 73, 65], [57, 75, 67], [58, 70, 62], [59, 68, 60],
        [60, 64, 56], [61, 60, 52], [62, 65, 57], [63, 67, 59], [64, 68, 60], [65, 69, 61],
        [66, 70, 62], [67, 72, 64], [68, 75, 67], [69, 80, 72]
      ]);

      var options = {
        hAxis: {
          title: 'Time'
        },
        vAxis: {
          title: 'Popularity'
        },
        series: {
          1: {curveType: 'function'}
        }
      };

      var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
      chart.draw(data, options);
    }

 

 

수정해보자!

1. x축을 1~100까지하고
2. dogs, cats, cows의 값을 0 ~ 10 사이의 랜덤한 숫자로
3. 1초에 한 번씩 새로운 그래프를 그리세요.

 

1. 값을 만드는 함수와 그래프를 그리는 함수를 따로 분리한 것

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    <div id="chart_div"></div>

  </body>
  <script>
  // 방법 1. 내가 한 것... 값을 만드는 함수와 그래프를 그리는 함수를 따로 분리
  var graphValue;
  function randomData() {
    graphValue = [];
    for (var i=1; i<=100; i++) {
      var ranDogsInt = parseInt(1 + Math.random() * 10);
      var ranCatsInt = parseInt(1 + Math.random() * 10);
      var ranCowsInt = parseInt(1 + Math.random() * 10);
      graphValue.push([i, ranDogsInt, ranCatsInt, ranCowsInt]);
    }
    return graphValue;
  }
  // 방법 1. 내가 한 것... 값을 만드는 함수와 그래프를 그리는 함수를 따로 분리
  setInterval(function () {
    graphValue = randomData();
    drawCurveTypes();
  }, 1000);

  google.charts.load('current', {packages: ['corechart', 'line']});
  // 방법 1. 내가 한 것...
  google.charts.setOnLoadCallback(drawCurveTypes);

  function drawCurveTypes() {
      var data = new google.visualization.DataTable();
      data.addColumn('number', 'X');
      data.addColumn('number', 'Dogs');
      data.addColumn('number', 'Cats');
      data.addColumn('number', 'Cows');

      // 방법 1.
      data.addRows(graphValue);

      var options = {
        hAxis: {
          title: 'Time'
        },
        vAxis: {
          title: 'Popularity'
        },
        series: {
          1: {curveType: 'function'}
          // 1: {curveType: 'none'}
        }
      };

      var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
      chart.draw(data, options);
  }

  </script>
</html>

 

2. 함수 안에 전부 다 넣은 것

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    <div id="chart_div"></div>

  </body>
  <script>
  // 방법 2. 교수님이 한 것. 값을 만들어 함수로 그리는 것까지 함수 하나에 다 넣음.
  var drawingGraphValue = [];
  function drawChart() {
    setInterval(function(){
      for(var i=1; i<=100; i++) {
        // array는 0부터 시작해야하므로 i-1을 해줬다.
        drawingGraphValue[i-1] = [i,
          1 + Math.floor(Math.random() * 10),
          1 + Math.floor(Math.random() * 10),
          1 + Math.floor(Math.random() * 10)];
      }
      drawCurveTypes(drawingGraphValue);
    }, 1000);
  }

  google.charts.load('current', {packages: ['corechart', 'line']});
  // 방법 2. 교수님이 한 것.
  google.charts.setOnLoadCallback(drawChart);

  function drawCurveTypes() {
      var data = new google.visualization.DataTable();
      data.addColumn('number', 'X');
      data.addColumn('number', 'Dogs');
      data.addColumn('number', 'Cats');
      data.addColumn('number', 'Cows');

      // 방법 2.
      data.addRows(drawingGraphValue);

      var options = {
        hAxis: {
          title: 'Time'
        },
        vAxis: {
          title: 'Popularity'
        },
        series: {
          1: {curveType: 'function'}
          // 1: {curveType: 'none'}
        }
      };

      var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
      chart.draw(data, options);
  }

  </script>
</html>

 

1. 설정으로 이동

Command + ',' 또는 File > Settings

 

2. Install

 

3. highlight-selected 검색 후 설치

 

4. 설정 편집

그림과 같이 2개 체크한다.

 

5. minimap 검색

미니맵도 설치하자

 

단축키

Command + ',' (Win : Ctrl + ',') : 설정창 열기

Control + K, B (Win : Ctrl + K, B) : 프로젝트 뷰(좌측 바) 열기

(Ctrl + Shift + F5) : 아톰 새로고침

 

 

Tag. 아톰 설치, 아톰 세팅, 아톰 셋팅, atom, Atom

 

 

HTML -> Table에서 테이블 사이즈를 정하고 합치고 'Generate' 누르고 'Copy'하면 끝!!

CSS 형태로 만들지 않고 th tr td 형태로 만들고 싶으면 'Do not generate CSS' 체크하면 된다.

<thead> </thead>태그는 지우는게 난 것 같다...

 

Markdown형태나 LaTeX 형태는 물론 Text 형태의 테이블도 생성해준다!

 

m.blog.naver.com/PostView.nhn?blogId=pjh445&logNo=220008543951&proxyReferer=https:%2F%2Fwww.google.com%2F

aboooks.tistory.com/81

 

'개발자 > HTML' 카테고리의 다른 글

HTML input 태그 button으로 페이지 이동하기  (0) 2020.11.12
자바스크립트 HTML 연습  (0) 2020.07.01
자바 HTML  (0) 2020.05.29
HTML 테이블 구조 (Python 웹크롤링)  (0) 2020.05.04
HTML CSS  (0) 2020.04.16

+ Recent posts