블로그제목

두번째블로그

Regular Expression to Format a Number String

Introduction

We discussed a regular expression used to format a number string by adding commas every three digits. The regular expression is (\d)(?=(?:\d{3})+(?!\d)) and it is used with the replace method in JavaScript to add commas to the number string.

Regular Expression Breakdown

We broke down the regular expression into its components:

  • (\d): This is a capture group that matches any single digit.
  • (?=...): This is a positive lookahead that matches the following pattern without including it in the match.
  • (?:...): This is a non-capturing group that groups together the following pattern without creating a capture group.
  • \d{3}: This matches any three digits.
  • +: This matches one or more of the previous pattern.
  • (?!\d): This is a negative lookahead that matches the following pattern only if it is not followed by a digit.

Regular Expression Explanation

We explained that the regular expression matches any single digit that is followed by one or more groups of three digits that are not followed by a digit. This effectively matches every digit in the number string except for the ones at the end that are not part of a group of three.

Example Process

We provided an example process to demonstrate how the regular expression works. Suppose we have the number string “1000000000”. The regular expression matches the first digit “1” because it is followed by a group of three digits “000”. It then matches the second digit “0” because it is followed by another group of three digits “000”. It continues to match every digit in the number string that is followed by a group of three digits. When it reaches the end of the string, it stops matching because the last digit “0” is not followed by a group of three digits.

Conclusion 1

We concluded that the regular expression (\d)(?=(?:\d{3})+(?!\d)) can be used to format a number string by adding commas every three digits. The regular expression matches every digit in the string except for the ones at the end that are not part of a group of three.

More Techniques

  1. Negative Lookahead: This is similar to positive lookahead, but it matches if the pattern does NOT occur after the current position. It is denoted by (?!pattern).

  2. Capturing Groups with Names: Instead of just using numbered capturing groups like $1, you can assign names to capturing groups for easier reference. For example, (?\d{4}) would match a four-digit number and capture it in the group named “year”.

  3. Quantifiers: Quantifiers allow you to specify how many times a character or group should be matched. For example, a{3,5} would match “aaa”, “aaaa”, or “aaaaa”, but not “aa”.

  4. Alternation: Alternation allows you to match one pattern OR another. It is denoted by the | symbol. For example, (cat|dog) would match “cat” or “dog”.

  5. Character Classes: Character classes allow you to match a range of characters. For example, [a-z] would match any lowercase letter, and [0-9] would match any digit.

  6. Non-Capturing Groups: Similar to capturing groups, non-capturing groups allow you to group parts of the pattern together without capturing the match. This can be useful for improving performance and simplifying the regular expression. Non-capturing groups are denoted by (?:pattern).

  7. Anchors: Anchors allow you to match a pattern at a specific position in the string. The most common anchors are ^, which matches the start of a line, and $, which matches the end of a line.

  8. Backreferences: Backreferences allow you to match a pattern that was previously matched by a capturing group. This can be useful for finding repeated patterns in a string. Backreferences are denoted by \number, where number is the number of the capturing group you want to reference.

  9. Lookbehinds: Lookbehinds are similar to lookaheads, but they match a pattern that precedes the current position in the string. Lookbehinds are denoted by (?<=pattern) for a positive lookbehind and (?<!pattern) for a negative lookbehind.

  10. Unicode Characters: Regular expressions can match any Unicode character by using escape sequences. For example, \p{L} matches any letter, and \p{N} matches any digit.

  11. Character Classes: Character classes allow you to match a single character from a set of characters. They are denoted by square brackets, for example [aeiou] matches any vowel.

  12. Alternation: Alternation allows you to match one of several alternatives. It is denoted by the pipe character |. For example, (cat|dog) matches either “cat” or “dog”.

  13. Quantifiers: Quantifiers allow you to match a certain number of repetitions of a pattern. The most common quantifiers are * for zero or more, + for one or more, and ? for zero or one.

  14. Dot: The dot . matches any character except a newline character.

  15. Word Boundaries: Word boundaries allow you to match a pattern only when it appears at the beginning or end of a word. They are denoted by \b.

  16. Greedy vs. Lazy Matching: By default, regular expressions are greedy and match as much as possible. You can use a ? after a quantifier to make it lazy and match as little as possible.

  17. Character Escapes: Character escapes allow you to match characters that have special meaning in regular expressions. For example, to match a literal dot character, you need to escape it with a backslash: ..

  18. Substitution: Regular expressions are often used to replace text. You can use the replace() method to substitute matches with other text.

  19. Flags: Regular expressions can have flags that modify their behavior. The most common flags are i for case-insensitive matching and g for global matching.

  20. Grouping: Grouping allows you to treat a pattern as a single unit and apply a quantifier to it. Groups are denoted by parentheses, for example a(bc)+ matches “abc”, “abcbc”, “abcbcbc”, and so on.

Conclution 2

얼마전 코딩테스트 보러갔다가 종이 시험을 보는것을 보고 1차로 놀랐다. 그리곤 문제를 보는데 1번부터 내 머리속에 아무것도 없는것을 느끼고 2차로 놀랐다. IDE의 힘을 빌려 AI HELPER의 빌려 살다보니 그렇다. 특히 정규식같은 부분은 한번 써놓고 오래 보질 않으니 다 휘발되고 머리에 남은게 없었다.
그렇게 계속 생각없이 살다가 Fiddler로 결제모듈을 뜯다보니 왠걸 갑자기 내가 정규식이 아닌 리스트로 풀었던 답이 딱 나오길래 글을 남긴다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class amount {
public static void main(String[] args) {
String str = "10000000";
String formattedStr = str.replaceAll("(\\d)(?=(?:\\d{3})+(?!\\d))", "$1,");
// str의 한글자 한글자를 정규식을 대입해서 일치하면 캡처한 변수 $1로 바꾼다.
// (\\d): 첫번째 차례인 문자가 숫자인경우, 값을 캡쳐한다. 일치하지않으면 다음 차례 문자를 검사한다.
// (?=) : 전방탐색(positive lookahead)으로 str 끝까지 미리 일치하는지 검사 한다.
// (?:) : 괄호안에 있어도 캡쳐하지 않는다는 뜻이다.
// \\d{3}+ : 숫자 3개로 이루어진 세트가 여러개 있는것을 말한다.
// (?!) : 이 다음이 아닌경우를 찾는다.
// \\d : 숫자를 뜻한다.
// 종합: 맨 처음부터 문자 한개를 잡고 그뒤로 숫자 3개가 붙어있는 세트가 쭉 이어지는지 검사한다. 딱 맞아 떨어지면 캡쳐해놓은 맨 처음 숫자에 ,를 더해서 교체한다.
// 만약 딱 맞아 떨어지지 않으면 그냥 통과한다.
System.out.println(formattedStr);
}
}

  1. What is the difference between an enumeration and a structure in Swift?

    In Swift, an enumeration (or “enum” for short) is a value type that represents a group of related values. Enums are defined using the enum keyword and can be used to define a set of possible values for a variable, for example, a list of error codes, or a list of days of the week. Enums can also have associated values, which can be used to store additional information for each case.
    A structure (or “struct” for short) is also a value type in Swift that represents a group of related values, but it can store multiple values of different types, similar to a class. Structures can have properties, methods, and initializers, and they can also conform to protocols.

    요약: 열거형(“Enum”)은 관련 값 그룹 유형이며 값 집합을 정의하는데 사용한다. 구조체(“Struct”)는 관련 값 그룹 인것 맞지만 서로 다른 유형의 여러 값을 저장할 수 있으며, 속성, 메서드, 이니셜라이저를 갖고 프로토콜을 따를 수도 있다.

  2. Can you give an example of using optional chaining in Swift?

    Optional chaining in Swift is a way of calling properties, methods, or subscripts on an optional value, where the optional value may be nil. If the optional value is nil, the result of the optional chaining is nil, otherwise, it returns the result of the operation.

    Here’s an example of using optional chaining in Swift:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    class Person {
    var name: String
    var address: Address?

    init(name: String) {
    self.name = name
    }
    }
    class Address {
    var street: String
    var city: String

    init(street: String, city: String) {
    self.street = street
    self.city = city
    }
    }
    let john = Person(name: "John")
    if let street = john.address?.street {
    print(street)
    } else {
    print("john does not have an address")
    }
    john.address = Address(street: "Jong-ro",city: "Seoul")
    if let street = john.address?.street {
    print(street)
    } else {
    print("john does not have an address")
    }

    Output:

    1
    2
    john does not have an address
    Jong-ro
  3. What is the purpose of the “defer” statement in Swift?

    The “defer” statement in Swift is used to execute a block of code just before the current function returns. The code in the “defer” block is executed regardless of how the function returns, whether it returns normally, or due to an exception being thrown.
    The main use case for the “defer” statement is to perform cleanup tasks, such as freeing up resources, closing files, or releasing locks, even if the function exits early due to an error. This helps to simplify the code by centralizing the cleanup code in a single place and making it easier to understand the code flow.

    요약: “defer”는 함수 반환 전 정상, 예외 여부와 관계없이 마지막에 실행되는것으로 오류로 인해 조기에 종료되더라도 파일닫기, 잠금해제같은 작업을 수행하기 위함이다.

    Here’s an example of using the “defer” statement in Swift:

    1
    2
    3
    4
    5
    6
    7
    8
    func processFile(fileName: String) throws {
    let file = try openFile(fileName)
    defer {
    closeFile(file)
    }
    // perform some processing on the file
    try processContents(file)
    }

    In this example, the openFile function is called to open a file, and the closeFile function is called in the defer block to close the file. The closeFile function is guaranteed to be called, even if the processContents function throws an error, because the defer block is executed just before the processFile function returns. This makes it easy to ensure that the file is always closed, even if an error occurs during the processing of the file.

  4. What is the difference between a class and a structure in Swift?

    In Swift, a class and a structure are both used to define custom data types, but they have some key differences.
    Classes are reference types, which means that when you assign a class instance to a variable, you are actually creating a reference to the instance, not a copy of it. This means that multiple variables can refer to the same instance, and changes to the instance made through one reference will be visible through all references.
    Structures, on the other hand, are value types, which means that when you assign a struct instance to a variable, you are creating a copy of the instance. This means that changes to the instance made through one reference will not affect other references to the same instance.
    Classes can also inherit from other classes and can be used to create objects, while structures cannot. Structures, however, are generally faster and more efficient than classes, especially when it comes to small instances, and they are also easier to manage and debug because they are self-contained.

    요약: 구조체, 클래스 모두 데이터 유형 정의에 사용. 클래스를 인스턴스에 할당하면 복제가 아닌 참조를 만드는것이나, 구조는 복사본이 생성된다. 클래스는 다른 클래스에서 상속할 수 있고 객체를 만드는데 사용할 수 있지만 구조체는 그렇지 않다. 인스턴스가 작으면 구조체가 더 효율적일 수 있다.

  5. Can you explain the difference between a class method and an instance method in Swift?

    Class methods are called on the class itself, while instance methods are called on instances of the class.
    Class methods can be called without creating an instance of the class, while instance methods require an instance to be created.
    Class methods have the class keyword in their declaration, while instance methods do not.

    클래스 메서드는 클래스 자체에서 인스턴스 할당 없이 호출되는 반면,
    인스턴스 메서드는 클래스를 인스턴스에 할당 한 뒤에 그 인스턴스에서 호출된다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class Car {
    static func displayClassName() {
    print("Car")
    }
    func displayInstanceName() {
    print("Instance of Car")
    }
    }
    Car.displayClassName() // Output: Car
    let myCar = Car()
    myCar.displayInstanceName() // Output: Instance of Car
  6. Can you give an example of using generics in Swift?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    func sortArray<T: Comparable>(_ array: [T]) -> [T] {
    return array.sorted()
    }

    // Example usage:
    let unsortedInts = [5, 3, 9, 2, 7]
    let sortedInts = sortArray(unsortedInts)
    print(sortedInts) // Output: [2, 3, 5, 7, 9]

    let unsortedStrings = ["cat", "dog", "bird", "fish"]
    let sortedStrings = sortArray(unsortedStrings)
    print(sortedStrings) // Output: ["bird", "cat", "dog", "fish"]

    함수 sortArray는 Comparable프로토콜을 따르는 제네릭 타입 T를 사용한다. Comparable을 따른다는것은 비교연산자를 사용할 수 있다는것이다.

  7. What is the difference between optional binding and optional chaining in Swift?

    Optional binding is used to safely unwrap an optional value and bind it to a new variable or constant, and it’s typically used when you need to perform operations on the unwrapped value.
    In this example, we use optional binding with if let to safely unwrap the optional value optionalName and bind it to the new constant name. If the optional value is nil, the code inside the else block will be executed. Here’s an example:

    1
    2
    3
    4
    5
    6
    7
    let optionalName: String? = "John"

    if let name = optionalName {
    print("Hello, \(name)!")
    } else {
    print("Hello, stranger.")
    }

    옵셔널 바인딩은 안전하게 변수를 언랩하기 위함이다.

    Optional chaining, on the other hand, is used to safely access a property or call a method on an optional value, without needing to first unwrap the value. In this example, we use optional chaining with the ? operator to safely access the street property of the person’s address property. If person.address is nil, the code inside the else block will be executed instead.
    Here’s an example:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    struct Person {
    var name: String
    var age: Int
    var address: Address?
    }

    struct Address {
    var street: String
    var city: String
    var state: String
    }

    let person = Person(name: "John", age: 30, address: Address(street: "123 Main St", city: "Anytown", state: "CA"))

    if let street = person.address?.street { // <==
    print("He lives on \(street).")
    } else {
    print("No address found.")
    }

    반면 옵셔널체이닝은 안전하게 변수에 접근하기 위함이다.

  8. Can you explain the difference between class inheritance and protocol-oriented programming in Swift?

    Both class inheritance and protocol-oriented programming are ways to achieve code reuse and polymorphism in Swift, but they have different approaches and trade-offs.

    Class inheritance is a mechanism where a subclass inherits properties and methods from a superclass. The subclass can also override and add its own properties and methods. Class inheritance is a form of vertical code reuse because it defines a hierarchy of classes with shared functionality.

    => 클래스는 일부를 공유하는 계층적 구조이므로 수직적인 상속 형태라고 볼 수 있다.

    In this example, the Cat class inherits from the Animal class, which defines a name and sound property and a makeSound() method. The Cat class overrides the makeSound() method to provide its own implementation.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    class Animal {
    var name: String
    var sound: String

    init(name: String, sound: String) {
    self.name = name
    self.sound = sound
    }

    func makeSound() {
    print("\(name) makes \(sound)!")
    }
    }

    class Cat: Animal {
    init(name: String) {
    super.init(name: name, sound: "meow")
    }

    override func makeSound() {
    print("\(name) purrs.")
    }
    }

    let cat = Cat(name: "Whiskers")
    cat.makeSound() // Output: "Whiskers purrs." (Example of overriden func)

    Protocol-oriented programming, on the other hand, is a programming paradigm where functionality is defined in small, composable protocols that can be combined to create new types. This is a form of horizontal code reuse because it encourages the creation of many small protocols with specific functionality that can be combined and reused in different ways.

    다양한 방식으로 결합하고 재사용할 수 있는 작은 프로토콜의 생성=> 수평적 코드 재사용

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    protocol Movable {
    var speed: Double { get }

    func move()
    }

    class Car: Movable {
    var speed: Double

    init(speed: Double) {
    self.speed = speed
    }

    func move() {
    print("The car is moving at \(speed) mph.")
    }
    }

    class Plane: Movable {
    var speed: Double

    init(speed: Double) {
    self.speed = speed
    }

    func move() {
    print("The plane is flying at \(speed) mph.")
    }
    }

    let car = Car(speed: 60)
    let plane = Plane(speed: 500)

    let vehicles: [Movable] = [car, plane]

    for vehicle in vehicles {
    vehicle.move()
    }

    While protocols and class inheritance can achieve similar results in some cases, they have different strengths and use cases.

    One advantage of using protocols is that they allow for greater flexibility and modularity in your code. Protocols can be adopted by a wide range of types, including classes, structs, and enums. This means that you can create more specialized types that conform to a protocol, rather than having to subclass a more general type. This can help avoid issues with tight coupling and inheritance hierarchies that can arise with class inheritance.

    Additionally, protocols can be used to achieve polymorphism across types that don’t share a common superclass. With protocols, you can define a common set of requirements that any conforming type must implement, allowing you to work with a wider range of types that share a particular behavior.

    Another advantage of protocols is that they allow for composition over inheritance. With protocols, you can define small, modular interfaces that can be combined to create larger and more complex behaviors. This can make your code more flexible and easier to maintain, since you can reuse small pieces of functionality in different contexts.

    In summary, while protocols and class inheritance can both achieve code reuse and polymorphism, protocols have different strengths and use cases, including greater flexibility and modularity, better support for polymorphism across different types, and the ability to compose smaller pieces of functionality into larger behaviors.

    => 프로토콜은 더 큰 유연성과 모듈성을 허용하며, 클래스 뿐만 아니라 구조체, 열거형 등에서도 사용하며 하위 클래스로 분류하는게 아닌 프로토콜을 준수하는 유형으로 취급하여 클래스 상속에서 발생할 수 있는 강결합 및 상속 계층 문제를 방지한다.
    => 클래스 상속과 프로토콜을 동시에 사용이 가능하다.

  9. How does Swift handle type casting?

    In Swift, type casting is the process of checking the type of an instance at runtime and converting it to another type if possible. There are two types of type casting in Swift: upcasting and downcasting.

    Upcasting is the process of converting an instance of a subclass to an instance of its superclass. Since a subclass is guaranteed to have all the properties and methods of its superclass, upcasting is always safe in Swift.

    Here’s an example of upcasting and downcasting in Swift:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
        class Human {
    let name: String

    init(name: String) {
    self.name = name
    }
    }

    class Teacher: Human {
    let school: String

    init(name: String, school: String) {
    self.school = school
    super.init(name: name)
    }
    }

    class Student: Human {
    let school: String

    init(name: String, school: String) {
    self.school = school
    super.init(name: name)
    }
    }
    // Upcasting to the Human superclass
    let human: Human = Teacher(name: "John Doe", school: "Acme High School")
    let human2: Human = Student(name: "Jimmy Yo", school: "Batman School")

    var humanList = [Human]()

    humanList.append(human)
    humanList.append(human2)

    // Downcasting to the Teacher subclass
    for human in humanList {
    if let teacher = human as? Teacher {
    print("\(teacher.name) is teacher")
    } else if let student = human as? Student {
    print("\(student.name) is student")
    } else {
    print("\(human.name) is something else")
    }
    }

    Downcasting is the process of converting an instance of a superclass to an instance of a subclass. Since a superclass does not necessarily have all the properties and methods of its subclasses, downcasting is not always safe in Swift. To perform a downcast safely, you need to use the optional type-casting operator as? or the forced type-casting operator as!.

    => type을 쓰면 어떤 클래스인지 정확하게 알 수 있다.
    => 업캐스팅은 서브클래스를 어퍼클래스로 취급하고싶을때 사용 (포장)
    => 다운캐스팅은 업캐스팅된 서브클래스를 다시 서브클래스로 취급하고싶을때 사용 (포장 제거)

  10. Can you give an example of using the guard statement in Swift to handle optional values?

    guard. 진짜면 나간다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    func greet(name: String?) {
    guard let name = name else {
    print("No name provided")
    return
    }
    print("Hello, \(name)!")
    }

    greet(name: "John") // prints "Hello, John!"
    greet(name: nil) // prints "No name provided"

    greet 함수는 옵셔널 String을 파라메터로 받는다. 이 함수에서 guard는 name 파라메터가 nil인지 검사하고 조건이 true 이면 gurad를 나가고, false 이면(nil이면) guard 안을 돈다.

가. array 배열의 합

  1. for number in array { sum += number}
  2. array.reduce(0, { (first:Int, seconde:Int) -> Int in return first + second })
  3. array.reduce(0){$0+$1}
  4. array.reduce(0, +)

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment

블로그 구조 파악

GitHub Page에서 호스팅 지원

Hexo 라이브러리로 꾸미기, 배포 지원

최초 세팅순서

  1. github page 설정

  2. github repository 설정(public)

  3. node.js설치(패키지 다운로드해서 설치 진행)

  4. 블로그를 작업할 폴더에서 우클릭해서 git bash 실행

  5. git 의 ssh 확인

  6. npm install hexo-cli -g 으로 hexo 설치

  7. hexo init blog 로 blog 폴더에 관련파일 설치

  8. cd blog

  9. npm install

  10. git clone <레포 주소>

  11. npm install –save hexo-deployer-git

  12. _config.yml 파일 설정

    1
    2
    3
    4
    5
    url: 
    deploy:
    type: git
    repo: https://
    branch: main
  13. 깃허브에서 repo설정 진입 - pages

  14. 브랜치 고르고 라이브 페이지 설정하기

  15. git bash 로 돌아와서

  16. hexo deploy

여러곳에서 포스팅하려면

위 과정대로 deploy를 하면 로컬 blog 폴더 내 .deploy_git 내용들이 레포에 올라가게 된다. 그러나 준비에 필요한 나머지 파일이 없으므로 node모듈을 제외한 용량이 적은 리소스들을 전부 .gitignore에서 제외해주고

blog 안의 파일 전부를 private 레포에 따로 올려야 한다. 이것을 backup레포라고 한다면

새로운 장소에서 블로그를 이어가려면

  1. blog(backup)레포를 로컬과 클론한다.
  2. 아무 폴더에 HEXO 설치 후 node_modules만 blog 폴더에 넣는다.
  3. npm install –save hexo-deployer-git 설치한다.
  4. .deploy_git은 날려도 좋다. 문제가 있다면 rm -rf .deploy_git으로 날린뒤
  5. hexo g -d 로 다시 배포한다.
  6. clone된 repo도 commit한다.

새로운 장소에서 이전 테마를 설치하려면(next테마)

  1. git clone https://github.com/next-theme/theme-next-docs
  2. npm install hexo-theme-next
  3. 하면 기존것에 대충 잘 버무려짐

Hexo Admin 을 사용하여 관리하기

  1. npm install hexo-admin –save
  2. hexo s 하여 서버올리고 url 뒤에 /admin 붙여서 로그인한다.
  3. _config.yml 파일에 아이디 비밀번호 등을 체크한다.

참고:
별5
https://taetaetae.github.io/2016/09/18/hexo_github_blog/
별2
https://minsw.github.io/2021/01/18/Hexo-%EB%B8%94%EB%A1%9C%EA%B7%B8-%EC%8B%AC%ED%8F%90%EC%86%8C%EC%83%9D%EC%88%A0%ED%95%98%EA%B8%B0/
별4
https://techwell.wooritech.com/blog/2021/08/08/Hexo-%EB%B8%94%EB%A1%9C%EA%B7%B8/

0%