맨위로가기

리스트 캄프리헨션

"오늘의AI위키"는 AI 기술로 일관성 있고 체계적인 최신 지식을 제공하는 혁신 플랫폼입니다.
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.

1. 개요

리스트 컴프리헨션은 1969년 SETL 프로그래밍 언어에서 처음 소개된 개념으로, 특정 조건을 만족하는 원소들을 포함하는 새로운 리스트를 생성하는 간결한 방법을 제공한다. 파이썬, 하스켈, C# 등 다양한 프로그래밍 언어에서 지원하며, 데이터베이스 쿼리 언어인 XQuery와 XPath에서도 유사한 기능을 활용한다. 파이썬은 직관적인 구문을 제공하며, 하스켈은 강력하고 유연한 리스트 생성 방법을 지원한다. C#은 LINQ를 통해 객체 열거자를 조작하며, C++는 연산자 오버로딩 또는 STL 알고리즘을 통해 리스트 컴프리헨션과 유사한 기능을 구현한다. 모나드 컴프리헨션, 집합 컴프리헨션, 딕셔너리 컴프리헨션, 병렬 리스트 컴프리헨션 등 유사한 구조가 존재한다.

더 읽어볼만한 페이지

  • 프로그래밍 구성체 - 형 변환
    형 변환은 프로그래밍에서 변수의 데이터 타입을 변경하는 것으로, 암시적 형 변환과 명시적 형 변환으로 나뉘며, 객체 지향 프로그래밍에서는 업캐스팅과 다운캐스팅이 발생하고, 각 언어는 고유한 규칙과 방법을 제공하며 잘못된 형 변환은 오류를 유발할 수 있다.
  • 프로그래밍 구성체 - 연산자 오버로딩
    연산자 오버로딩은 프로그래밍 언어에서 기존 연산자를 사용자 정의 자료형에 대해 재정의하여 내장 자료형처럼 다루도록 하는 기능으로, 코드 가독성과 표현력을 높이지만 남용 시 코드 의미를 모호하게 만들 수 있다.
  • 빈 문단이 포함된 문서 - 광주고등법원
    광주고등법원은 1952년에 설치되어 광주광역시, 전라남도, 전북특별자치도, 제주특별자치도를 관할하며, 제주와 전주에 원외재판부를 두고 있다.
  • 빈 문단이 포함된 문서 - 1502년
    1502년은 율리우스력으로 수요일에 시작하는 평년으로, 이사벨 1세의 이슬람교 금지 칙령 발표, 콜럼버스의 중앙아메리카 해안 탐험, 바스쿠 다 가마의 인도 상관 설립, 크리미아 칸국의 킵차크 칸국 멸망, 비텐베르크 대학교 설립, 최초의 아프리카 노예들의 신대륙 도착 등의 주요 사건이 있었다.
리스트 캄프리헨션

2. 역사

리스트 컴프리헨션 개념은 1969년 SETL 프로그래밍 언어의 집합 형성 구조에서 비롯되었다.[19] 1973년 컴퓨터 알게브라 시스템 AXIOM에도 스트림을 처리하는 유사한 구조가 등장했다.[20] "컴프리헨션"이라는 용어는 1977년 로드 버스톨과 존 달링턴이 NPL 프로그래밍 언어 명세서에서 처음 사용하였다.[1] Smalltalk-80 언어에도 리스트 컴프리헨션 구성 요소가 포함되었다.

1980년대 버스톨과 달링턴의 NPL 연구는 여러 프로그래밍 언어에 영향을 주었지만, 모든 언어가 리스트 컴프리헨션을 채택한 것은 아니었다. 1985년 발표된 Miranda 프로그래밍 언어는 리스트 컴프리헨션을 포함한 대표적인 언어이며, 이후 Haskell 언어에도 영향을 미쳤다.

리스트 컴프리헨션은 데이터베이스 쿼리 표기법으로 제안되었으며,[2] Kleisli 데이터베이스 쿼리 언어에 구현되었다.[3]

3. 구문 및 의미

리스트 컴프리헨션은 일반적으로 다음과 같은 구성 요소를 갖는다. 출력 리스트의 요소 순서는 입력 리스트의 요소 순서를 따른다.

4. 다양한 프로그래밍 언어에서의 리스트 컴프리헨션

파이썬, Haskell, C#, C++, OCaml, Java, JavaScript, Ruby, Scala 등 다양한 프로그래밍 언어에서 리스트 컴프리헨션 또는 유사한 구문을 지원한다.[1] [19]


  • 파이썬은 간결하고 직관적인 리스트 컴프리헨션 구문을 제공한다.
  • Haskell은 리스트 컴프리헨션을 통해 리스트를 생성하는 강력하고 유연한 방법을 제공한다.
  • C# 3.0에는 LINQ(통합 언어 쿼리)라고 하는 관련 기능 집합이 존재하며, 객체 열거자를 조작하기 위한 쿼리 연산자가 정의되어 있다.
  • C++는 리스트 컴프리헨션을 직접 지원하지 않지만, 연산자 오버로딩이나 라이브러리를 활용하여 유사한 기능을 구현할 수 있다.

4. 1. Python

파이썬은 간결하고 직관적인 리스트 컴프리헨션(List Comprehension) 구문을 제공한다.[1]

리스트 컴프리헨션은 기존 리스트를 기반으로 새로운 리스트를 생성하는 간편한 방법이다. `for` 루프와 조건문을 결합하여 한 줄로 리스트를 생성할 수 있게 해주므로, 코드를 더 짧고 읽기 쉽게 만들어 준다.[2] PEP 202List Comprehensions|리스트 컴프리헨션영어에서 제안되었다.[3]

예를 들어, 0부터 9까지의 숫자의 제곱을 포함하는 리스트는 다음과 같이 만들 수 있다.

```python

squares = [x**2 for x in range(10)]

```

이 코드는 다음 코드와 동일한 결과를 생성한다.

```python

squares = []

for x in range(10):

squares.append(x**2)

```

리스트 컴프리헨션은 `if` 문을 사용하여 조건을 추가할 수도 있다. 예를 들어, 0부터 9까지의 숫자 중 짝수의 제곱만을 포함하는 리스트는 다음과 같이 만들 수 있다.

```python

even_squares = [x**2 for x in range(10) if x % 2 == 0]

4. 2. Haskell

Haskell은 리스트 컴프리헨션을 통해 리스트를 생성하는 강력하고 유연한 방법을 제공한다.

4. 3. C#

C# 3.0에는 LINQ(통합 언어 쿼리)라고 하는 관련 기능 집합이 존재하며, 객체 열거자를 조작하기 위한 쿼리 연산자가 정의되어 있다. C#은 LINQ를 통해 리스트 컴프리헨션과 유사한 기능을 제공한다.

```csharp

var s = Enumerable.Range(0, 100).Where(x => x*x > 3).Select(x => x*2);

```

또한, SQL을 연상시키는 대체 컴프리헨션 구문도 제공한다.

```csharp

var s = from x in Enumerable.Range(0, 100) where x*x > 3 select x*2;

```

LINQ는 전형적인 리스트 컴프리헨션 구현보다 뛰어난 기능을 제공한다. 컴프리헨션의 루트 객체가 IQueryable 인터페이스를 구현하는 경우, 컴프리헨션의 연결된 메서드를 단순히 실행하는 대신, 전체 명령 시퀀스가 추상 구문 트리(AST) 객체로 변환되어 IQueryable 객체에 전달되어 해석 및 실행된다.

이를 통해 IQueryable은 다음과 같은 작업을 수행할 수 있다.

  • 비호환적이거나 비효율적인 컴프리헨션 재작성
  • AST를 다른 쿼리 언어(예: SQL)로 변환하여 실행

4. 4. C++

C++는 리스트 컴프리헨션을 직접 지원하지 않지만, 연산자 오버로딩이나 라이브러리를 활용하여 유사한 기능을 구현할 수 있다.

  • 연산자 오버로딩 활용:
  • `|`, `>>`, `>>=` 등의 연산자를 오버로딩하여 "내장" 쿼리 DSL과 비슷한 표현 구문을 만들 수 있다.
  • 라이브러리 활용:
  • 지우기-제거 관용구: 컨테이너에서 특정 요소를 선택한다.
  • STL 알고리즘 `for_each`: 선택된 요소들을 변환한다.


```cpp

#include

#include

#include

using namespace std;

template

C comprehend(C&& source, const P& predicate, const T& transformation)

{

// 결과 리스트 초기화

C d = forward(source);

// 조건(predicate)에 맞는 요소 제거

d.erase(remove_if(begin(d), end(d), predicate), end(d));

// 변환(transformation) 적용

for_each(begin(d), end(d), transformation);

return d;

}

int main()

{

list range(10); // 0으로 초기화된 10개 요소 리스트

iota(begin(range), end(range), 1); // 1부터 10까지 채움

list result = comprehend(

range,

[](int x){return x*x <= 3;}, // 제곱이 3 이하인 요소 선택

[](int &x){x *= 2;}); // 선택된 요소 2배

// result는 {2, 4}가 된다.

}

```

C++에서 리스트 컴프리헨션과 유사한 기능을 구현하기 위한 다른 방법들은 다음과 같다.

  • Boost Range 라이브러리: 범위(range)에 필터링, 변환 등을 적용할 수 있는 어댑터를 제공한다.


```cpp

counting_range(1,10) | filtered( _1*_1 > 3 ) | transformed(ret( _1*2 ))

```

  • 매크로 및 `<<` 연산자 오버로딩: 이 방법은 스레드 안전하지 않다.


```cpp

list N;

list S;

for (int i = 0; i < 10; i++)

N.push_back(i);

S << list_comprehension(3.1415 * x, x, N, x*x > 3) // S = {3.1415*x | x in N, x*x > 3}

```

  • 클래스 및 연산자 오버로딩: head/tail 슬라이싱 및 `|` 연산자를 사용한 필터링을 제공한다.


```cpp

bool even(int x) { return x % 2 == 0; }

bool x2(int &x) { x *= 2; return true; }

list l, t;

int x, y;

for (int i = 0; i < 10; i++)

l.push_back(i);

(x, t) = l | x2; // l의 첫 요소를 x에, 나머지를 t에 넣고 x2 적용

(t, y) = t; // t의 첫 요소를 y에, 나머지를 t에 넣음

t = l < 9; // l에서 9보다 작은 요소들로 t 구성

t = t < 7 | even | x2; // t에서 7보다 작은 짝수들을 x2 적용

```

  • LEESA (Language for Embedded Query and Traversal)[18]:
  • 연산자 오버로딩을 사용하여 X-Path와 유사한 쿼리를 구현하는 C++ 내장 DSL이다.
  • XML 데이터 처리에 사용된다.
  • `>>` 연산자는 XPath의 `/` 구분자에 해당한다.
  • 전략적 프로그래밍은 XPath의 `//` 구분자를 구현한다.


```cpp

// XPath: "catalog/book/author/name"

std::vector author_names =

evaluate(root, catalog_ >> book_ >> author_ >> name_);

// XPath: "catalog//name"

std::vector author_names =

evaluate(root, catalog_ >> DescendantsOf(catalog_, name_));

// XPath: "catalog//author[country=="England"]"

std::vector author_names =

evaluate(root, catalog_ >> DescendantsOf(catalog_, author_)

>> Select(author_, [](const author & a) { return a.country()=="England"; })

>> name_);

4. 5. 기타 언어

OCaml에서는 [http://batteries.forge.ocamlcore.org/ OCaml Batteries Included] 라이브러리를 통해 리스트 컴프리헨션과 유사한 기능을 사용할 수 있다.[19] Java에서는 Java 8 이상에서 스트림(Stream) API를 통해, JavaScript에서는 배열 메서드(map, filter, reduce 등)를 체이닝하여 리스트 컴프리헨션과 비슷한 결과를 얻을 수 있다. Ruby에서는 Enumerable 모듈의 메서드, Scala는 자체적인 for 컴프리헨션을 지원하여 리스트 컴프리헨션과 같은 기능을 제공한다.

5. 유사 구조

리스트 컴프리헨션과 유사한 구조를 가진 다른 프로그래밍 언어 기능은 다음과 같다.


  • 모나드 컴프리헨션: 하스켈에서 모나드 컴프리헨션은 모나드에 대한 리스트 컴프리헨션의 일반화이다.[1] 하스켈에는 모나드 내포 표기법이라는 표기법이 있는데, 이는 함수형 프로그래밍에서의 리스트 내포 표기법을 모나드로 일반화한 것이다.[1]
  • 집합 컴프리헨션: 파이썬 3.x 버전과 2.7 버전은 리스트 컴프리헨션과 유사한 집합 컴프리헨션을 지원하여 리스트 대신 집합을 생성한다.[1] 래킷 집합 컴프리헨션도 리스트 대신 래킷 집합을 생성한다.[1]
  • 딕셔너리 컴프리헨션: 파이썬 2.7 버전에서는 딕셔너리 컴프리헨션 구문이 도입되어, 리스트 대신 파이썬 딕셔너리를 생성한다.[1] 래킷 해시 테이블 컴프리헨션은 래킷 해시 테이블(래킷 딕셔너리 유형의 한 구현)을 생성한다.[1]
  • 병렬 리스트 컴프리헨션: 글래스고 하스켈 컴파일러(Glasgow Haskell Compiler)는 병렬 리스트 컴프리헨션(또는 zip-컴프리헨션)이라는 확장을 통해, 리스트 컴프리헨션 내에서 여러 개의 독립적인 한정자 분기를 병렬로 평가한다.[1] 이는 zip과 유사하게 작동한다. Racket은 "for"와 "for*" 키워드로 병렬 및 중첩 버전을 구분하며, Python에서는 `zip` 함수를 사용하여 유사한 기능을 구현한다. 줄리아에서도 배열을 사용하여 동일한 결과를 얻을 수 있다.

5. 1. 모나드 컴프리헨션

Haskell에서 모나드 컴프리헨션은 모나드에 대한 리스트 컴프리헨션의 일반화이다.[1] Haskell에는 모나드 내포 표기법이라는 표기법이 존재한다.[2] 이는 함수형 프로그래밍에서의 리스트 내포 표기법을 모나드로 일반화한 것이다.[1]

5. 2. 집합 컴프리헨션

파이썬 버전 3.x와 2.7은 리스트 컴프리헨션과 유사한 집합 컴프리헨션을 지원한다. 집합 컴프리헨션은 리스트 대신 집합을 생성한다.[1]

```python

>>> s = {v for v in 'ABCDABCD' if v not in 'CB'}

>>> print(s)

{'A', 'D'}

>>> type(s)



>>>

```

래킷 집합 컴프리헨션은 리스트 대신 래킷 집합을 생성한다.[1]

```scheme

(for/set ([v "ABCDABCD"] #:unless (member v (string->list "CB")))

v))

5. 3. 딕셔너리 컴프리헨션

파이썬 2.7 버전에서는 딕셔너리 컴프리헨션에 대한 새로운 구문이 도입되었다. 이는 리스트 컴프리헨션과 형태가 유사하지만, 리스트 대신 파이썬 딕셔너리를 생성한다.[1]

```python

>>> s = {key: val for key, val in enumerate('ABCD') if val not in 'CB'}

>>> s

{0: 'A', 3: 'D'}

```

Racket 해시 테이블 컴프리헨션은 Racket 해시 테이블(Racket 딕셔너리 유형의 한 구현)을 생성한다.[1]

```scheme

(for/hash ([(val key) (in-indexed "ABCD")]

#:unless (member val (string->list "CB")))

(values key val))

5. 4. 병렬 리스트 컴프리헨션

글래스고 하스켈 컴파일러(Glasgow Haskell Compiler)는 병렬 리스트 컴프리헨션(또는 zip-컴프리헨션)이라는 확장을 지원한다. 이는 리스트 컴프리헨션 내에서 여러 개의 독립적인 한정자 분기를 허용하는 것이다. 쉼표로 구분된 한정자는 종속적("중첩")이지만, 파이프로 구분된 한정자 분기는 병렬로 평가된다. 이는 멀티스레딩을 의미하는 것이 아니라, 분기가 zip된다는 것을 의미한다.

```haskell

  • - 일반적인 리스트 컴프리헨션

a = [(x,y) | x <- [1..5], y <- [3..5]]

  • - [(1,3),(1,4),(1,5),(2,3),(2,4) ...

  • - zip을 이용한 리스트 컴프리헨션

b = [(x,y) | (x,y) <- zip [1..5] [3..5]]

  • - [(1,3),(2,4),(3,5)]

  • - 병렬 리스트 컴프리헨션

c = [(x,y) | x <- [1..5] | y <- [3..5]]

  • - [(1,3),(2,4),(3,5)]

```

Racket의 표준 라이브러리에는 "for"와 "for*"라는 두 개의 키워드로 구분되는, 병렬 버전과 중첩 버전의 두 가지 컴프리헨션이 있다.

```scheme

> (for*/list ([x (in-range 1 6)] [y (in-range 3 6)]) (list x y))

'((1 3) (1 4) (1 5) (2 3) (2 4) (2 5) (3 3) (3 4) (3 5) (4 3) (4 4) (4 5) (5 3) (5 4) (5 5))

> (for/list ([x (in-range 1 6)] [y (in-range 3 6)]) (list x y))

'((1 3) (2 4) (3 5))

```

Python에서는 `zip` 함수를 사용하여 병렬 리스트 컴프리헨션과 유사한 기능을 구현할 수 있다.

```python

# 일반적인 리스트 컴프리헨션

>>> a = [(x, y) for x in range(1, 6) for y in range(3, 6)]

[(1, 3), (1, 4), (1, 5), (2, 3), (2, 4), ...

# 병렬 (zip을 이용한) 컴프리헨션

>>> b = [x for x in zip(range(1, 6), range(3, 6))]

[(1, 3), (2, 4), (3, 5)]

```

줄리아에서는 리스트 대신 배열을 사용한다는 점을 제외하면 사실상 동일한 결과를 얻을 수 있다.

```julia

# 일반적인 배열 컴프리헨션

>>> a = [(x, y) for x in 1:5 for y in 3:5]

# 병렬/zip된 배열 컴프리헨션

>>> b = [x for x in zip(1:3, 3:5)]

6. XQuery와 XPath에서의 활용

XQueryXPath는 데이터베이스 질의 언어로, 리스트 컴프리헨션과 유사한 구문을 사용하여 XML 데이터를 처리한다.

XPath에서 다음 표현식은:

```xquery

/library/book//paragraph[@style='first-in-chapter']

```

개념적으로 일련의 "단계"로 평가되며, 각 단계는 목록을 생성하고 다음 단계는 이전 단계의 출력에서 각 요소에 필터 함수를 적용한다.[4]

XQuery에서는 전체 XPath를 사용할 수 있지만, 더 강력한 컴프리헨션 구조인 FLWOR 문도 사용된다.[5]

```xquery

for $b in //book

where $b[@pages < 400]

order by $b//title

return



{$b//title}

{($book//paragraph)[1]}



```

여기서 XPath //book는 시퀀스(일명 목록)를 생성하기 위해 평가된다. where 절은 기능적 "필터"이고, order by는 결과를 정렬한다. `shortBook` XML 조각은 실제로 다른 함수형 언어에서 발견되는 'map' 접근 방식을 사용하여 시퀀스의 각 요소에 대해 XML을 구축/변환하는 익명 함수이다.

따라서 다른 함수형 언어에서 위의 FLWOR 문은 다음과 같이 구현될 수 있다.

```xquery

map(

newXML(shortBook, newXML(title, $1.title), newXML(firstPara, $1...))

filter(

lt($1.pages, 400),

xpath(//book)

)

)

```

이러한 언어는 기본적으로 데이터베이스 접근 언어이다. 전체 리스트 (때로는 XML 데이터베이스 전체)를 가져와 조작하는 것은 계산 시간상 불가능하기 때문에, 리스트 컴프리헨션의 개념이 더욱 중요해진다.

7. 한국 프로그래밍 커뮤니티에서의 리스트 컴프리헨션

(이전 출력이 비어있으므로, 수정할 내용이 없습니다. 원본 소스와 요약이 제공되지 않았기 때문에 섹션 제목에 맞는 내용을 새롭게 생성하는 것도 불가능합니다.)

참조

[1] 간행물 Some history of functional programming languages https://www.cs.kent.[...]
[2] 문서 Comprehensions, a query notation for DBPLs http://portal.acm.or[...]
[3] 문서 The functional guts of the Kleisli query system http://portal.acm.or[...]
[4] 웹사이트 2.1 Location Steps http://www.w3.org/TR[...] W3C 1999-11-16
[5] 웹사이트 XQuery FLWOR Expressions https://www.w3school[...]
[6] 웹사이트 Single-variable List Comprehension in C++ using Preprocessor Macros http://mfoliveira.or[...] 2011-01-09
[7] 웹사이트 C++ list comprehensions http://www.tedunangs[...] 2011-01-09
[8] 웹사이트 Language for Embedded Query and Traversal (LEESA) http://www.dre.vande[...]
[9] 문서 Comprehensions, a query notation for DBPLs http://portal.acm.or[...]
[10] 문서 The functional guts of the Kleisli query system http://portal.acm.or[...]
[11] 웹사이트 2.1 Location Steps http://www.w3.org/TR[...] W3C 2008-12-24
[12] 웹사이트 XQuery FLWOR Expressions https://www.w3school[...] 2020-04-17
[13] 웹사이트 Chapter 1. Range 2.0 https://www.boost.or[...] 2020-04-16
[14] 웹사이트 Range Adaptors https://www.boost.or[...] 2020-04-16
[15] 웹사이트 Chapter 20. Boost.Lambda - 1.72.0 https://www.boost.or[...] 2020-04-16
[16] 웹사이트 Single-variable List Comprehension in C++ using Preprocessor Macros http://mfoliveira.or[...] 2011-01-09
[17] 웹사이트 C++ list comprehensions http://www.tedunangs[...] 2011-01-09
[18] 웹사이트 Language for Embedded Query and Traversal (LEESA) http://www.dre.vande[...] 2020-04-17
[19] 문서 Comprehensions, a query notation for DBPLs http://portal.acm.or[...]
[20] 문서 The functional guts of the Kleisli query system http://portal.acm.or[...]
[21] 웹인용 2.1 Location Steps http://www.w3.org/TR[...] W3C 2017-11-19
[22] 웹인용 XQuery FLWOR Expressions http://www.w3schools[...] 2011-10-07
[23] 웹인용 Single-variable List Comprehension in C++ using Preprocessor Macros http://mfoliveira.or[...] 2017-11-19
[24] 웹인용 C++ list comprehensions http://www.tedunangs[...] 2017-11-19
[25] 웹인용 Language for Embedded Query and Traversal (LEESA) http://www.dre.vande[...]



본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.

문의하기 : help@durumis.com