2014-04-05 2 views
2

매우 큰 .csv 파일을 읽고 구문 분석하는 데 encoding/csv을 사용하고 있습니다.
임의로 선을 선택하고 몇 가지 테스트를 통과해야합니다.
나의 현재 솔루션은 명백한 문제가 전체를 읽고 내가 많은 메모리를 필요로하는 데 시간이 오래 걸립니다 lines
에서이동 중에 텍스트 파일에서 임의의 행을 읽습니다.

reader := csv.NewReader(file) 
lines, err := reader.ReadAll() 

무작위 선택 라인과 같은 전체 파일을 읽는 것입니다.

질문 :
내 질문에 encoding/csvio/reader 대신 한 번에 전체를로드하는 임의의 줄을 읽어 그것을 사용하는 방법이 나에게주는입니까?
io/reader에 대해 더 많은 것을 알기에 더 많은 호기심이 생깁니다. 결국에는 한 번 읽고 메모리에 액세스하면 결국 무작위로 줄을 찾아내는 것이 더 효율적 일 것입니다. 디스크.

답변

4

Apokalyptik의 대답은 당신이 원하는 것과 가장 가깝습니다. 독자는 깃발이므로 무작위로 건너 뛰는 것은 불가능합니다.

주어진 줄을 읽었을 때 유치 확률을 선택하면 문제가 발생할 수 있습니다. 입력 줄을 충분히 잡히지 않고 파일의 끝에 도달하거나 줄을 너무 빨리 잡을 수 있습니다. 좋은 표본을 얻지 못한다. 어느 것이 먼저 정확하게 추측하는 것보다 가능성이 큽니다. 왜냐하면 먼저 파일에 얼마나 많은 행이 있는지를 모르기 때문입니다.

정말 필요한 것은 reservoir sampling입니다.

기본적으로 파일을 한 줄씩 읽습니다.각 줄, 당신은 그것을 보유할지 여부를 선택하십시오 : 당신이 읽는 첫 번째 줄, 당신은 1/1 잡고 그것을 가지고 있습니다. 두 번째 줄을 읽은 후에는 1/2 사람이 가지고있는 것을 바꿀 수 있습니다. 세 번째 줄 이후에는 그 대신에 1/2 * 2/3 = 1/3 기회가 있습니다. 따라서 1/N 개의 주어진 행을 가질 확률이 있습니다. N은 읽은 행의 수입니다. 여기에 more detailed look at the algorithm이 있습니다 (이 단락에서 혼자만 말한대로 구현하지 마십시오). .

0

encoding/csv 당신에게 당신에게 csv.Reader (csv.NewReader의 정의에 패키지 자격의 부족주의를주는 io.Reader를 제공하지 않습니다 [1]이 반환 Reader는 동일한 패키지에 속한다는 것을 나타냅니다.

csv.Reader 구현을 유일한 방법은 당신이보고, 자신 만 CSV 파서를 작성하는 짧은 원하는 일을 할 수있는 방법이없는 것 같습니다.

[1] http://golang.org/pkg/encoding/csv/#NewReader

+2

당신이 옳긴하지만 분명히하기 위해'csv.Reader'는'io.Reader'를 구현합니다. 그래서'csv.Reader' *는 실제로'io.Reader'입니다. – Matt

2

T 그는 가장 간단한 해결책은 테스트 할 것인지 아니면 버릴 것인지 결정할 때 각 라인을 읽을 때 결정을 내려야한다는 것입니다 ... 귀하의 결정을 무작위로 만들어 RAM에 전체를 보관할 필요가없는 경우 ... 통과하십시오 테스트를 실행 한 파일을 통해 ... 비 임의 배포 테스트에서도 동일한 스타일을 사용할 수 있습니다 (예 : X 바이트 이후 또는 x 줄 이후 등)

1

내 제안은 미리 입력 파일을 랜덤 화하는 것입니다. 필요에 따라 SHUF

http://en.wikipedia.org/wiki/Shuf

를 사용하는 것은 다음 당신은 단순히 처음 n 행을 읽을 수 있습니다.

이것은 io/독자에 대해 더 많이 배우는 데 도움이되지 않지만 그럼에도 불구하고 문제를 해결할 수 있습니다.

관련 문제