이 데이터를 저장하는 가장 효율적인 방법은 무엇입니까?


9

오래된 VB 코드를 다시 작성해야합니다. 나는 그것이 어떻게 작동하는지 이해하지만, 그들이 한 일을하는 훨씬 효율적인 방법이 있다고 생각합니다. 나는 그것이 무엇인지 알 수 없습니다. 다음은 데이터 요구 사항과 관련하여 실제로 내가 해야하는 것과 비슷한 것으로 고안된 예입니다.

사용자는 GUI에서 자동차 제조업체, 제조사, 모델 및 색상을 선택해야합니다. 다음과 같은 큰 텍스트 파일이 있습니다.

Ford Truck F150 red
Ford Truck F150 blue
Ford Truck F150 black
Ford Truck F150 silver
Ford Truck F250 red
Ford Truck F250 green
Ford Sedan Taurus red
Ford Sedan Taurus green
Ford Sedan Taurus white
Ford...
...

Subaru SUV Forester blue
Subaru SUV Forester red
Subaru SUV Outback Black
Subaru SUV Outback Green
Subaru SUV Outback Blue
Subaru SUV Outback Red
Subaru...
...

etc.

따라서 첫 번째 선택이 스바루 인 경우 두 번째 상자 (만들기) 에는 스바루가 트럭 이 아니므로 트럭을 선택할 수있는 옵션이 없어야합니다 . 마찬가지로 Ford, Sedan 및 Taurus를 선택하면 마지막 상자 (색상)에 파란색을 선택할 수있는 옵션이 표시 되지 않습니다 . 아니면 블랙 또는 빨강, 녹색 또는 흰색 이외의 것.

내가 코드를 작성한 사람들은 이것을 파이썬 (python-y psuedocode)으로 생각해 냈습니다.

def getValidOptions():
    items = []
    for i from 0 to numRows:
        options = getLine().split()
        if selectingManufacturer:
            if options[0] not in items:
                items.append(options[0])
        else if selectingMake:
            if selectedManufacturer == options[0] and options[1] not in items:
               items.append(options[1])
        else if selectingModel:
            if selectedManufacturer == options[0] and selectedMake == options[1] and options[2] not in items:
                items.append(options[2])
        else if selectingColor:
            if selectedManufacturer == options[0] and selectedMake == options[1] and selectedModel == options[2] and options[3] not in items:
                items.append(options[3])
    return items

나는 그것이 알고리즘 수준과 구문 수준 모두에서 끔찍하다고 생각합니다. 하나, 그것은 제대로 수행하면 몇 줄을 통해 읽을 필요가있을 때 전체 파일을 통해 구문 분석합니다. 이를 더욱 비효율적으로 만들기 위해 실제 데이터에는 4 개가 아닌 6 가지 옵션 중에서 선택할 수 있습니다. 이는 데이터 복제 량을 고려하여 필요한 것보다 많은 데이터를 저장하는 것입니다.

파일에 데이터를 저장하는 다른 방법이나 getValidOptions함수를보다 예쁘고 효율적 으로 만들기 위해 파싱하는 다른 방법을 찾고 있습니다. 내가 할 수있는 방법이 있습니까?


2
왜 데이터베이스를 사용하지 않습니까?
Tulains Córdova

답변:


6

내가 읽은 다른 모든 대답은 소프트웨어 개발의 두 가지 기본 규칙을 무시하는 것 같습니다.

  • 먼저 요구 사항을 명확히하십시오 (특히 성능 및 스토리지 요구 사항)

  • 단순하고 멍청하게 유지하십시오 ( KISS 참조 )

당신은 "텍스트 파일이 크다"라고 썼지 만 너무 크게 쓰지 않았습니다 . 따라서 파일을로드하는 데 실제로 너무 오래 걸리지 않고 IT 부서 나 다른 사람이 낭비되는 디스크 공간에 대해 불평하지 않고 파일을 유지 관리하는 데 문제가 있다고 아무도 불평하지 않는 경우 파일 형식을 그대로 두십시오. 단순성의 가치.

또한 알고리즘의 효율성에 대해 불평하고 있습니다. 실제로 알고리즘은 그다지 효율적이지 않지만 매우 큰 이점이 있습니다. 그것은 매우 간단하고 효과적입니다. 충분히 효율적이면 조기 최적화를 적용하지 마십시오.

따라서 프로그램이 충분히 빠르게 작동한다고 가정 해 보자. 우선 단순성과 DRY 원칙에 따라 코드를 어떻게 개선 할 수 있는가? 그리고 현재 코드가 DRY가 아니기 때문에 실제로 개선해야 할 점입니다. 예를 들어, "상위 레벨"의 옵션이 현재 행과 일치하는 경우 거의 동일한 코드 블록 테스트의 4 배가 나타나고 동일한 유형의 "추가"호출 (실제 코드에서는 반복이 발생 함) 당신이 쓴대로 적어도 6 번). 숫자 선택 레벨을 도입하거나 이미 선택된 옵션을 순서가 지정된 목록으로 전달하면이를 피할 수 있습니다. 의사 코드를 사용하면 라인을 따라 무언가가 생깁니다.

# selectedOptions is a list, containing either nothing, or "selectedManufacturer"
# or [selectedManufacturer, selectedMake], ..., and so on
def getValidOptions(selectedOptions):
    items = []
    level = selectedOptions.size()
    for i from 0 to numRows:
        options = getLine().split()
        if selectedOptions == options[0:level-1] and options[level] not in item:
            items.append(options[level])
    return items

따라서 이것은 더 이상 반복 코드가없는 동일한 알고리즘입니다.

분명히 getValidOptions한 번 이상 (레벨 당 한 번 이상) 호출해야하므로 한 번만 최적화를 적용하는 것이 좋습니다 (아직 그렇지 않은 경우). getLine함수가 데이터를 주 메모리에서 가져와야하며 디스크에서 파일을 반복해서 읽습니다.


numRows 루프 전에 "level = selectedOptions.size ()"를 이동하려고합니다.
AI Breveleri

6

여러분이 가진 데이터는 나무와 같은 구조를 가지고 있습니다. 각 제조업체마다 모델 트리가 있고 각 모델마다 색상 등이 있습니다.

따라서이 데이터의 프로세스를 두 단계로 분리 할 수 ​​있습니다.

  1. 텍스트 파일을 업데이트 한 후에는 해당 파일을 처리하여 트리 구조로 변환해야합니다.
  2. 응용 프로그램을로드 할 때는 트리 구조 만로드합니다.

트리 구조는 해시 , 연관 배열 또는 Java, PHP, Javascript 또는 Python과 같은 언어로 된 사전 으로 구현할 수 있습니다 . 이 구조를 사용하면 다음이 가능합니다.

  • 첫 번째 열쇠는 제조업체입니다.
  • 이들의 값은 각 키가 모델 인 또 다른 해시 또는 사전 입니다.
  • 그들의 가치는 색상입니다. 또는 다른 구조는 키에 세 번째 레벨을 유지하고 네 번째 레벨을 가치로 유지합니다.
  • 등등...

프로그래밍 언어에 따라 더 빠르거나 느리게 구현 될 수 있습니다. 예를 들면 다음과 같습니다.

  • C # : Tree 구조 1을 구현 한 다음 직렬화 가능으로 표시 할 수 있습니다.
  • VB.Net : 하나의 응용 프로그램에서 트리 구조를 생성하고 파일로 직렬화 할 수 있습니다.
    • 이를 위해 Runtime.Serialization.Formatters.Binary.BinaryFormatter유용 할 수는 있지만 VB.Net으로 직렬화하는 데 전문가는 아닙니다.
  • Javascript : 앱을로드 할 때마다로드되어야하는 JSON 파일에서 트리 구조를 생성 할 수 있습니다.
  • PHP : 직렬화 된 버전의 트리 데이터 구조를 생성하거나 JSON도로드 할 수 있습니다.
  • Java : 해당 데이터 구조를 직렬화 Class하여 인터페이스를 구현 하는 데이터 구조를 작성할 수 있습니다 java.io.Serializable.

참고 문헌 :

1 : https://dvanderboom.wordpress.com/2008/03/15/treet-implementing-a-non-binary-tree-in-c/-C
#에서 트리를 구현하는 방법에 대한 완전한 설명.
-누군가가 해당 객체 를 직렬화 하는 것에 대한 의견 과 해당 답변에 대한 답변을 찾으십시오 .


1
예, 나무 사용에 대해 생각했지만 C #에 내장 된 트리 구조 (내가 아는)가 없기 때문에 그것이 가장 좋은 아이디어인지는 알지 못합니다. 프로젝트는 매우 작기 때문에 알 수 없습니다. tree with an arbitrary number of nodes구현 에 많은 시간을 할애 할 가치가 있습니다 .
James

아직 C #에 대한 전문가는 아니지만 적어도 Java 및 PHP와 같은 다른 언어에서는 일종의 사전을 가질 수 있으며 각 키는 다른 사전의 가치를 가질 수 있습니다.
Nicolás

답변을 업데이트했습니다. 해시 또는 사전 대안에 대해 어떻게 생각하는지 확인하십시오. 나는 또한 흥미로운 기사에 대한 참조를 추가했습니다.
Nicolás

3

데이터를 저장하는 간단한 방법 중 하나는 SQLite 데이터베이스에 데이터를 넣는 것입니다. SQLite는 대부분의 SQL 데이터베이스와 달리 응용 프로그램 파일 형식으로 사용하기에 적합합니다. 이 방법에는 몇 가지 이점이 있습니다.

  1. 시리얼 라이저 또는 디시리얼라이저를 코딩 할 필요가 없습니다.
  2. 수많은 기존 프로그램에서 파일을 편집하고 쿼리 할 수 ​​있습니다.
  3. 질문에서 언급 한 조건부 혼잡함을 피할 수 있습니다. 드롭 다운을 제한하려면 각 열에 대해 간단한 where 절을 생성하십시오 (예 :) select distinct model where manufacturer='ford' and color = 'red'.

이렇게하면 SQL을 배울 수 있지만 사용자 정의 파일 형식을 배울 필요는 없습니다.


1

파일의 행에 무작위로 액세스 할 수 있으므로 파일을 레코드 배열로 취급 할 수 있다고 가정합니다. 무작위로 회선에 액세스 할 수없는 경우 보유하고있는 알고리즘이 최선의 방법입니다.

가장 빠른 액세스를 위해 데이터를 6 개 파일로 저장하십시오. 여기서 각 파일은 다음 파일의 색인입니다.

플랫 파일 색인을 작성하는 방법에는 여러 가지가 있습니다. 나는 보통 첨자 범위를 사용합니다. 사용자가 각 항목을 선택할 때 범위를 사용하여 다음 파일의 읽기를 제한하십시오.

다음은 제공 한 샘플 데이터에 대한 인덱스를 만드는 방법입니다.

물론 파일을 정렬해야합니다. 나는 설명을 위해 줄 번호를 매겼다. 줄 번호는 파일에 나타나지 않아야합니다.

--| file3.dat |--
 0 Ford Truck F150 red
 1 Ford Truck F150 blue
 2 Ford Truck F150 black
 3 Ford Truck F150 silver
 4 Ford Truck F250 red
 5 Ford Truck F250 green
 6 Ford Sedan Taurus red
 7 Ford Sedan Taurus green
 8 Ford Sedan Taurus white
 9 Subaru SUV Forester blue
10 Subaru SUV Forester red
11 Subaru SUV Outback Black
12 Subaru SUV Outback Green
13 Subaru SUV Outback Blue
14 Subaru SUV Outback Red

첫 번째 색인을 작성하려면 파일에서 처음 세 필드의 고유 한 조합마다 레코드를 작성하십시오. 각 레코드에 해당 조합이 나타나는 첫 번째 및 마지막 줄 번호를 저장하십시오.

--| file2.dat |--
 0 Ford Truck F150       0   3
 1 Ford Truck F250       4   5
 2 Ford Sedan Taurus     6   8
 3 Subaru SUV Forester   9  10
 4 Subaru SUV Outback   11  14

두 번째 인덱스는 첫 번째 인덱스의 처음 두 필드를 사용하여 유사하게 구성됩니다.

--| file1.dat |--
 0 Ford Truck        0   1
 1 Ford Sedan        2   2
 2 Subaru SUV        3   4

세 번째는이 경우 최상위 수준 인 인덱스입니다.

--| file0.dat |--
 0 Ford          0   1
 1 Subaru        2   2

나는 개념을 지나치게 설명하고 있다고 생각하지만 일반적으로 마지막 필드를 삭제하고 중복 레코드를 제거하여 색인을 만듭니다.

중복 데이터를 제거하여 파일 스토리지 요구 사항을 추가로 줄일 수 있습니다.

예를 들어, 각 인덱스 레코드의 "첫 번째"첨자는 항상 이전 레코드의 "마지막"첨자보다 하나 이상이거나 이전 레코드가없는 경우 0입니다. 따라서 "첫 번째"첨자를 저장할 필요가 없습니다. 설명을 위해 아래에 그대로 두겠습니다.

또한 각 레코드의 마지막 필드 만 사용하여 선택 목록을 채우므로 다른 필드를 저장할 필요가 없습니다.

인덱스 캐스케이드의 최소 변환은 다음과 같이 보입니다. 여기서 틱 '은 실제로 파일에 저장되지 않은 숫자를 나타냅니다.

--| file0.dat |--
 0' Ford         0'   1
 1' Subaru       2'   2

--| file1.dat |--
 0' Truck        0'   1
 1' Sedan        2'   2
 2' SUV          3'   4

--| file2.dat |--
 0' F150         0'   3
 1' F250         4'   5
 2' Taurus       6'   8
 3' Forester     9'  10
 4' Outback     11'  14

--| file3.dat |--
 0' red
 1' blue
 2' black
 3' silver
 4' red
 5' green
 6' red
 7' green
 8' white
 9' blue
10' red
11' Black
12' Green
13' Blue
14' Red

색인에서 선택 목록을 채울 때 이전 색인에서 사용자가 선택한 "첫 번째"및 "마지막"첨자를 사용하여 읽은 행을 제한합니다.

예:

모든 첫 번째 선택 목록을 채 웁니다 file0.dat. (스바루 포드)

사용자는 "Ford"를 선택합니다. 해당 첨자는 0과 1입니다.

두 번째 선택 목록을 0 ​​~ 1의 행에서 채 웁니다 file1.dat. (트럭, 세단)

사용자는 "세단"을 선택합니다. 해당 첨자는 2와 2입니다.

보시다시피, 예를 들어 "Ford" "Sedan" "Taurus"와 같이 사용자가 선택한 시간까지 file3.dat네 번째 선택 목록을 채우려면 6 ~ 8 행만 읽으면됩니다 .

다소 긴 설명에 대해 사과하지만 여기에 너무 늦어서 짧은 설명을 쓸 시간이 없습니다.

추가 : 추가로 생각하면 파일을 하나로 연결할 수 있습니다.

--| file.dat |--
 0' -            1'   2
 1' Ford         3'   4
 2' Subaru       5'   5
 3' Truck        6'   7
 4' Sedan        8'   8
 5' SUV          9'  10
 6' F150        11'  14
 7' F250        15'  16
 8' Taurus      17'  19
 9' Forester    20'  21
10' Outback     22'  25
11' red          -'   -
12' blue         -'   -
13' black        -'   -
14' silver       -'   -
15' red          -'   -
16' green        -'   -
17' red          -'   -
18' green        -'   -
19' white        -'   -
20' blue         -'   -
21' red          -'   -
22' Black        -'   -
23' Green        -'   -
24' Blue         -'   -
25' Red          -'   -

이것은 첫 번째 첨자 범위를 포함하기 위해 더미 첫 줄이 필요하다는 점을 제외하고는 여러 파일 버전과 똑같이 사용됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.