본문 바로가기

Python(알고리즘,문제풀이)/프로그래머스(입문100제)

코딩테스트입문 / n의 배수 고르기

728x90

📚문제

출처 : 프로그래머스 / n의 배수 고르기(https://school.programmers.co.kr/learn/courses/30/lessons/120905)

 

📝풀이

def solution(n, numlist):
    multiple = [ i for i in numlist if i % n ==0]
    return multiple

 

리스트 컴프리헨션을 이용해서 n의 배수들의 배열을 생성하였다

꽤 빨리 풀었지만 이 코드 전에 

n의배수가 아닌 수들을 배열에서 제거하는 코드에서 의문점이 생겨서 블로그를 작성하였다

 

numlist = [4, 5, 6, 7, 8, 9, 10, 11, 12]
n= 3
for i in numlist:
    if i % n != 0:
        numlist.remove(i)
-----------------------------------------
[5, 6, 7, 8, 9, 10, 11, 12]

 

처음에 이런 식으로 작성했는데

이렇게 나왔다

for 문을 반복하는동안 numlist의 변화를 살펴봤다

 

numlist = [4, 5, 6, 7, 8, 9, 10, 11, 12]
n= 3

for i in numlist:
    if i % n != 0:
        numlist.remove(i)
        print(numlist)
-----------------------------------------
[5, 6, 7, 8, 9, 10, 11, 12]
[5, 6, 8, 9, 10, 11, 12]
[5, 6, 8, 9, 11, 12]

 

??? 

numlist의 range만큼 반복하지도 않고 3번만 돌며 결과도 전혀 뜻밖이다..

 

혹시 numlist에 재할당을 해주지 않아서인가 했는데

if문 내에서 numlist = numlist.remove(i)를 해주면

AttributeError: 'NoneType' object has no attribute 'remove'

이런 에러가 발생한다.

 

왜냐하면 list.remove() 메서드는 원본 리스트 자체를 직접 수정하는 작업이고

새로운 리스트를 반환하지 않기 때문이다.

 

 

그래서 i값의 변화도 print()해서 보기로했다

numlist = [4, 5, 6, 7, 8, 9, 10, 11, 12]
n= 3

for i in numlist:
    print(i)
    if i % n != 0:
        numlist.remove(i)
        print(numlist)
-----------------------------------------
4
[5, 6, 7, 8, 9, 10, 11, 12]
6
7
[5, 6, 8, 9, 10, 11, 12]
9
10
[5, 6, 8, 9, 11, 12]
12

이렇게 보니 알 것 같다

 

처음에 4는 제거되면서 리스트 길이가 -1이 되면서 5는 건너뛰었다

6은 3의배수이니 넘어가고 7이 제거되며 또 리스트의 길이가 -1이된다

이 과정에서 8도 건너 뛰게된다 그래서 5, 8, 11 이살아 있게 되어서 이런 결과가 발생한다

for문에서 remove를 사용하여 리스트를 수정하면 이렇게 결과가 뒤죽박죽이 된다

=> for문에서 원본 리스트를 훼손하는 remove 사용하지말자! 

 

어떻게 이렇게 나오는건지 전혀 이해가 되지 않다가 하나씩 뜯어보니 이해가 되었다 ㅎㅎ

리스트 컴프리헨션으로 간단히 풀긴 했지만,

이렇게 원하던 결과와 전혀 다르게 나오면 

하나씩 살펴보고 기록해놓는게 좋은 것 같다

 

+ 만약 이 방법을 계속 사용하고 싶다면

numlist = [4, 5, 6, 7, 8, 9, 10, 11, 12]
numlist_b = numlist.copy()
n= 3

for i in numlist_b:
    if i % n != 0:
        numlist.remove(i)
print(numlist)

 

1. numlist가 리스트이므로 .copy()를 사용하여 동일한 배열 1세트 복사

2. for문은 numlist_b를 돌게하고 ( 값 동일 하므로)

3. numlist(원본)에서 제거해 나간다 

728x90