2012-12-21 3 views
4

나는 파서를 연구 중이다. 소스 텍스트에서 값을 가져옵니다. 변수 이름, 개수 등이 크게 달라질 수 있다는 것을 미리 알지 못합니다. 소스의 각 섹션은 일부 값만 제공하며 전체 목록은 제공하지 않습니다. 이러한 값은 현재 KeyValuePair와 비슷하지만 처음부터 작성된 사용자 정의 클래스 목록에 저장됩니다. 소스에서 검색되는 것을키/값 쌍 목록을 데이터 테이블로 변환

샘플 :

| KeyA | KeyB | KeyC | KeyD | 
+-------+-------+-------+-------+ 
| ValA1 | ValB1 |  | ValD1 | 
|  |  | ValC2 |  | 
|  | ValB3 |  | ValD3 | 

:

Section 1: 
    KeyA = ValA1 
    KeyB = ValB1 
    KeyD = ValD1 
Section 2: 
    KeyC = ValC2 
Section 3: 
    KeyB = ValB3 
    KeyD = ValD3 

등 지금

, 나는의 형태로 데이터 그리드로 사용자에게이 정보를 표시하고 싶습니다 현재 각 섹션에서 발견 된 모든 값을 반복하고, 열이 있는지 확인하십시오. 그렇지 않은 경우 새 열을 만듭니다. 열이있는 경우 - 각 행/열에 값을 추가합니다. 그런 다음 결과 DataTable을 DataGrid에 다음과 같이 연결합니다.

dg.ItemSource=dt.AsDataView(); 

이것은 의도 한대로 완벽하게 작동하지만 너무 느립니다.

내가 속도를 낼 수있는 방법에 대한 의견을 보내 주시면 감사하겠습니다. 초기 저장 또는 DataTable 로의 변환 또는 데이터를 바인딩하여 사용자에게 동일한 프리젠 테이션을 제공하는 다른 방법.

의 C#, WPF, .NET 프레임 워크 4.5

업데이트 : 모든 로딩 및 처리가 사전에 이루어집니다. 준비된 데이터는 처리 된 섹션의 트리로 저장됩니다. 속성의 하나 인 각 섹션에는 키/값 쌍의 목록이 있습니다. 각 섹션에는 주어진 DataTable에 값을 채우는 클래스가 있습니다.

e.e. 각 섹션은 방법을 가지고

File1 
    + Section 1 on level 1 
    | + Section 1 
    | + Section 2 
    + Section 2 on level 1 
    + Section 3 on level 1 
    | + Section 1 
    | + Section 2 
    | + Section 3 
    | + Section 4 
    + Section 4 
File2 ... 

: 백엔드 데이터처럼 보이는 일부 DataTable을 더 높은 수준 요소에 의해 호출되는

public void CollectValues(DataTable target) {...} 

(처음에 - 빈과 잘 지내 채워지고).

private List<CustomValue> Values; 

CustomValue 클래스의 모든 이미 발견 & 처리 된 값을 보유하고있다 :

각 섹션은 내부 변수를 포함한다. CustomValue ~ = KeyValuePair,하지만 처리 루틴이 추가되었습니다.

그래서 준비되지 않은 DataTable이 비어있는 요청 된 레벨에서 CollectValues가 호출됩니다 (최상위, 다른 것일 수 있음). CollectValues는 현재 수준의 목록에서 사용 가능한 모든 값을 반복하고 (foreach) DataColumn에 필요한 이름 (target [Value.Key]! = null)이 있는지 확인하기 전에 한 번에 대상 DataTable 1에 추가합니다. 필요한 경우 각각의 값을 추가하기 전에 시도하십시오. 메타 코드의 경우 :

public void CollectValues(DataTable target) 
{ 
    DataRow dr = target.Rows.Create(); 
    foreach(var pair in Values) 
    { 
     if(target[pair.Key]==null) target.Columns.Add(...); 
     dr[pair.Key] = pair.Value; 
    } 
    foreach(var child in Children) 
     child.CollectValues(target); 
} 

왜이 특정 부분 값은 유사한 루틴의 일부에 불과합니다. 다른 루틴도 같은 데이터 세트에서 비슷하게 크롤링하고 다른 것들 (대부분 DataTable이없는 목록으로 작업)을 검색합니다. 즉, 모두 즉시 작동합니다.DataTable 수집은 결과 DataGrid가 채워지도록 1 개의 소스에 대해 몇 초가 걸릴 수 있습니다.

값의 평균 값이 거의 1000을 초과하지 않습니다 (10 열 100 행). DataTable은 완전히 채워진 후에 만 ​​DataGrid에 연결됩니다.

크기 정보 : 소스 - 대개 2 ~ 10 개 파일. 각 원본 텍스트 크기는 100Kb - 100MB입니다. 일반적인 파일 크기는 약 1-2MB입니다. 일반적으로 메모리의 백엔드 데이터 크기는 100MB 미만입니다.

그리고 다시 강조 표시하십시오. 걱정스런 DataTable 일뿐입니다. 하이라이트, 섹션, 소스 검색, 필터링 등 - 모든 것이 제 예상 내에 있습니다. 따라서 우선 키/값 쌍 목록에서 DataTable 로의 변환을 최적화하는 방법이나 프로세스를 가속화하기 위해 초기에 (처리 후) 값을 다르게 저장하는 방법을 찾고 있습니다.

희망 사항은 충분한 정보를 제공합니다. 현재 크기를 줄이려면 소스를 나열하지 않습니다.

+0

은 피벗 테이블처럼 보입니다. 피벗을 생성하는 코드를 게시하십시오. 어떻게 데이터를 검색하고 있습니까? 대기 시간이 데이터를 가져 오는 좋은 기회이거나 데이터의 실제 작동이 아닌 데이터의 양입니다. –

+4

슬로우 파트 란 무엇입니까? –

+0

데이터를 별도로 가져 와서 이미 처리 된 백엔드에 저장합니다. 선택한 파일을로드하는 중에 발생합니다. 한 번만 로딩/처리가 완료되면 사용자가 인터페이스로 작업합니다. 느린 부분은 컬렉션/변환 부분으로 보입니다.상당히 큰 트리를 반복하면서 반복적으로 진행되며 각 섹션에서 DataTable을 채우도록 요청합니다. – chersun

답변

0

DataTable이 느립니다. 그것은 많은 것들을합니다.

모든 문자열이있는 경우, 내가 그런 수동 ColValues ​​[I] 구문을 사용하여 데이터 그리드에 열을 바인드해야 모음

List<String> ColNames; 
List<String> ColValues; 

List<ColValues> RowsColValues; 

을 만들 것입니다.

그리고 속도를 위해 ListView GridView를 사용하십시오.
DataGrid가 느리고 대량으로 Gridview와 비교됩니다.
그러나 GridView는 편집하지 않습니다.

아니야.
전 정확히이 작업을 수행하지만 다른 시나리오를 수행합니다.
사용자는보고 싶은 열을 선택합니다.

DyamicColumns

+0

변경을 위해 GridView를 시도해 봅니다. 제 경우에는 편집이 실제로 필요하지 않습니다. 조금 의미가있는 바인딩을 자세히 설명해 주시겠습니까? 헤더와 값으로 값 이름이 필요합니다. 각각의 행/헤더에 있어야합니다.이 경우 어떻게해야하는지 잘 모르겠습니다. – chersun

+0

헤더에 ColNames를 사용하십시오. – Paparazzi

1

내가 여기에 사용하는 DataTable을 이외의 데이터 구조를 찾을 것입니다. 나에게 당신이 필요로하는 것 같아요. Dictionary<string, Dictionary<int, CustomValue>>입니다. string이 열 이름이고 int은 데이터 행의 ID이고 CustomValue은 데이터 자체입니다. 이미 장소에 pair.ID이없는 경우

public void CollectValues(Dictionary<string, Dictionary<int, CustomValue>> target) 
{ 
    foreach(var pair in Values) 
    { 
     if(target[pair.Key]==null) target.Add(new Dictionary<int, CustomValue>()); 
     target[pair.Key].Add(pair.ID, pair.Value); 
    } 
    foreach(var child in Children) 
     child.CollectValues(target); 
} 

, 당신은 각 개체가 다른 ID를 가질 수 있도록 카운터 변수 (중 static 또는 각 호출과 함께 전달)를 사용할 수 있습니다.


이것은 데이터의 각 세트가 아닌 역방향보다 갖는 열과 행으로 값을 저장 더 적합 할 수 있습니다. 그것은 각각 Dictionary이 하나의 행을 나타내는 IEnumerable<Dictionary<string, CustomValue>>입니다. target.Select(x => x.Key).Distinct()으로 모든 열을 제거합니다.

+0

이 구조로는별로 작동하지 않았습니다. – chersun

+0

나는 종종 ComboBox 바인딩을 위해 Dictionary를 사용하는데 SelectedValuePath를'Key'에 그리고 DisplayMemberPath를'Value'에 바인딩합니다. 이렇게하면 "apple", "banana"등과 같은 문자열에 대해 1부터 5까지의 키를 가질 수 있습니다. 사용자가 문자열을 볼 수 있지만 selectedvalue에 대해 ComboBox에 요청하면 키가 연관됩니다 (일반적으로, 데이터베이스 p rimary ID). – Joe

+0

@chersun - 음. 좋은 질문. 직접 바인딩 할 수 있다고는 생각하지 않지만 필요한 값을 가져올 수 있습니다. 'target.Keys'는 열 목록이고,'target.Values.Select (x => x.Values)'는 각 행의 값 목록입니다. 그래도 그걸 가지고 놀았지만 결과를 읽는 데 가장 좋은 데이터 구조인지는 잘 모르겠습니다. 다른 제안으로 편집하겠습니다. – Bobson

관련 문제