1) For문 사용

2) Stream 사용

3) java.util.Arrays.deepToString() 사용

 

 

- 참고

- https://hianna.tistory.com/511

Vue 공부를 하다보니, 그전에는 가볍게만 썼던 JS를 더 많이 보고 쓰게 되었다.

그 와중에 배열과 객체의 차이,

더 정확하게는 객체의 프로퍼티를 이용하는 것과 배열을 이용하는 것이 무엇이 다른지 궁금해졌다.

 


대부분의 객체지향 언어에서도 배열과 객체는 존재하고 그 차이는 명확하다.

배열은 주어진 자료형을 정해진 크기대로 넣어두고 인덱스를 이용해서 접근하는 방식으로 구성된다.

 

let arr = ['Javascript', 'is', 'Fun!'];

for (let i = 0; i < arr.length; i++) {
	console.log(i + ' : ' + arr[i] + '\n');
}

 

 

객체는 자바스크립트에서 리터럴 값을 제외한 모든 것이라고 할 수 있다. (심지어 함수 까지도!)

그리고 객체는 내부적으로 0개 이상의 데이터로 구성되어있는데, 이 때 데이터를 프로퍼티라고 한다.

프로퍼티는 키와 값으로 구성되어, 키를 통해서 접근할 수 있다.

(만약 프로퍼티가 문자열이 아니라면, 문자열로 변환이 된다.)

 

let obj = {
    name : 'js',
    fun : true
};

console.log(obj.name + ' ' + (obj['fun'] ? 'is fun!' : 'is not fun!'));

 

let arr = [1, 2, 3];
let obj = {
    1 : 1,
    2 : 2,
    3 : 3
};

console.log(`arr(${arr.length})`);
for (let i = 0; i < arr.length; i++) {
    console.log(arr[i]);
}

// cause undefined error
// console.log(`\nobj(${obj.length})`);
console.log(`\nobj`);
for (let i = 1; i <= 3; i++) {
    console.log(obj[i.toString()]);
}

객체와 배열은 3가지로 구분이 가능하다.

 

  1. 값의 참조 방식
    • 값의 참조는 배열의 경우 인덱스로 참조하기 때문에 number 가능하며, 객체는 문자열로만 가능하다.
  2. 값의 순서
    • 배열은 연속되는 값들의 집합이기에 순서가 존재하지만, 객체에 순서는 존재하지 않다.
  3. length 프로퍼티
    • 배열은 length 프로퍼티에 접근이 가능하지만, 객체는 length 프로퍼티에 접근이 불가능하다.

 


참고 : 모던 자바스크립트 Deep Dive

참고1 : Mozila MDN

'Language > JavaScript' 카테고리의 다른 글

JS에서 Template literals가 동작하지 않을 때  (0) 2022.07.29

파이썬에서는 배열을 선언할 때 여러가지 방법들이 있다.

 

list_1 = []
list_2 = [] * 5
list_3 = [] for _ in range(5)

등등 여러가지가 있는데, 그중에서도 오늘은 for 문과 * 연산자를 이용한 배열 선언의 차이에 대해서 적어보고자 한다.

 

2차원 배열을 선언할 때는 3가지 방법을 쓸 수 있다.

 

 

첫 번째로 빈 리스트 생성 후 append로 더하기이다.

# 아예 빈 리스트를 생성 후 append로 더하기

list_1 = []
list_1.append([0, 0, 0])

print(list_1)

# [[0, 0, 0]]

다만 이 방법은 추후 코드를 통해서 append 해야하기 때문에, 실질적으로 append 하기 전까진 1차원 배열이라고 할 수 있다.

따라서 다음과 같은 코드를 실행하는 데 문제가 발생한다.

# Index Error 발생

list_1 = []

# IndexError: list index out of range
print(list_1[0][1])

list_1.append([0, 0, 0])

따라서 위와 같은 문제를 해결하기 위해 2가지 방법을 더 생각해 볼 수 있다.

 

 

두 번째로 * 연산자를 이용한 선언이다.

# * 연산자를 이용한 선언

list_1 = [[0] * 3] * 5

print(list_1[0][1])

list_1.append([1, 1, 1])

# 0

 

 

세 번째로는 for문을 이용한 선언이다.

# for문을 이용한 선언

list_1 = [[0 for col in range(3)] for row in range(5)]

print(list_1[0][1])

list_1.append([1, 1, 1])

# 0

 

두 번째와 세 번째를 모두 실행해보면 같은 결과를 출력하는 걸 볼 수 있다.

그렇기에 둘 다 같은 거라는 생각이 들 수 있다.

하지만 둘은 엄연히 다르다.

 

 

이걸 설명하기 위해서는 깊은 복사(Deep Copy)와 얕은 복사(Shallow Copy)에 대해서 알아야한다.

우선 깊은 복사는 변수나 객체가 가지고 있는 값을 그대로 복사하여, 다른 변수나 객체가 동일한 값을 가지게 하는 것이고,

얕은 복사는 변수나 객체를 참조하는 것이다.

 

즉 깊은 복사는 원본 객체와 복사된 객체는 별개의 객체이지만, 얕은 복사는 복사된 객체가 원본 객체를 참조하기 때문에 둘간의 연결성이 있다.

 

# 세로 길이가 3, 가로 길이가 2인 행렬이 있다고 했을 때,
# 이를 2차원 배열로 바꾸는 2가지 방법의 차이점

# 얕은 복사
list_1 = [[False] * 2] * 3
# 깊은 복사
list_2 = [[False for col in range(2)] for row in range(3)]

print(list_1)
print(list_2)
# [[False, False], [False, False], [False, False]]
# [[False, False], [False, False], [False, False]]

list_1[0][0] = True
list_2[1][1] = True

print(list_1)
print(list_2)
# [[True, False], [True, False], [True, False]]
# [[False, False], [False, True], [False, False]]

위와 같이 list_1은 [False] * 2로 각각의 요소들을 얕은 복사를 했기에,

[0][0]뿐만 아니라 [1][0], [2][0]까지도 값이 변경된 것을 확인 할 수 있다.

 

반대로 list_2는 for문을 통한 깊은 복사를 했기에,

[1][1] 요소만 변경되고, 나머지 요소에는 영향을 주지 않은 것을 볼 수 있다.

 

 

간혹 함수에 매개변수 값을 전달할 때 자주 나오는 pass by reference, pass by value도 이와 비슷한 맥락이라 볼 수 있다.

둘이 완전히 동일하진 않지만, 값을 전달 할 것인가, 참조할 것인가의 차이인 점에서는 같다.

 

 

 

파이썬에 익숙하지 않다보니, 얕은 복사인지도 모르고 쓰다가 수십 분을 허비한 경험으로 글을 쓰게 되었다.

다들 쉽다고 하는데, 왜 나는 이렇게 파이썬이 어려운지 잘 모르겠다

차근차근 시간을 두고 익혀봐야겠다.

'Language > Python' 카테고리의 다른 글

[Python] List Slicing  (0) 2022.08.09
# Created by ARA on 2022-08-09.

# 이것이 코딩테스트다
# Ch05-DFS/BFS-꼭 필요한 자료구조 기초

stack = []

# 삽입(5) - 삽입(2) - 삽입(3) - 삽입(7) - 삭제() - 삽입(1) - 삽입(4) - 삭제()
stack.append(5)
stack.append(2)
stack.append(3)
stack.append(7)
stack.pop()
stack.append(4)
stack.pop()

print(stack)
print(stack[::-1])

# Expected Output
# [5, 2, 3]
# [3, 2, 5]

코딩테스트 책을 보는데, 18번 줄에서의 stack[::-1]이 무엇을 의미하는지 이해가 안됐다.

그래서 인터넷을 찾아보고 알아본 걸 정리해본다.

 

일단 우선 python [] 연산자에 대해서 찾아봤다.

c++ 에서 검색했던 것과는 다르게 별 다른 내용이 나오질 않았다.

 

어쩌다보니 slicing이라는 키워드를 찾게 되었는데, 거기에 해당하는 내용이 있었다.

(막상 정식 문서 가서 찾아보려니 위와 같은 예제는 찾질 못하겠다... 혹시라도 나중에 찾게 되면 추가하겠다.)

 

이 사이트에서 문법을 설명하는데, 내가 알고 있는 것과 동일했다.

다만 뒤에 Step이 있는 지 몰랐다.

자세히 읽어보니 다음 요소(element)를 선택할 때 기준을 말하는 거 같았다.

 

# Return every 2nd item between position 2 to 7
L = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
print(L[2:7:2])
# Prints ['c', 'e', 'g']

예제 코드를 해석해 봤을 때, L 리스트에 있는 요소 중에서 2번 인덱스 부터 7번 미만 인덱스 까지 2의 간격으로 요소를 출력하라고 해석해볼 수 있다.

그림으로 표현하면 다음과 같다

'Language > Python' 카테고리의 다른 글

[Python] 2차원 배열을 선언할 때 주의할 점  (0) 2022.08.10

Template literals는 ES2015에 추가된 문자열에 변수명을 그대로 사용하게 하는 문법 설탕 (synatatic sugar)이다

 

기존에는 문자열 리터럴에 '(Apostrophe), "(Quotation Mark)를 사용했지만, 

Template literals를 사용하기 위해서는 `(Grave Accent)를 사용해야한다.

 

예를 들어서

 

그레이브 엑센트 대신 아포스트로피를 사용하면 다음과 같은 결과가 나온다.

let name = 'world';
console.log('Hello ${name}');

리터럴로 인식해 그대로 출력하는 걸 볼 수 있다.

 

이번에는 그레이브 엑센트로 사용했을 때이다.

let name = 'world';
console.log(`Hello ${name}`);

원하는 대로 잘 출력된 걸 볼 수 있다.

 

이외에도 다른 기능들이 많으니 MDN을 참고하는 게 좋을 거 같다.

 

Template literals(MDN)

 

'Language > JavaScript' 카테고리의 다른 글

[JS] 배열과 객체의 차이  (0) 2022.08.27

+ Recent posts