2010-12-13 8 views
4

청크로 파일을 읽는 기능이 있습니다.while 루프에서 변수 초기화

public static DataObject ReadNextFile(){ ...} 

그리고 데이터 객체는 다음과 같습니다

public DataObject 
{ 
    public string Category { get; set; } 

    // And other members ... 
} 

내가 뭘 원하는 어떻게 액세스합니까 때문에, 그것을 어떻게하는지 아마 아니다 알고 기본적으로 다음과 같은

List<DataObject> dataObjects = new List<DataObject>(); 

while(ReadNextFile().Category == "category") 
{ 
    dataObjects.Add(^^^^^ the thingy in the while); 
} 

입니다 방금 읽은 물건.

+0

확실합니까, 물어보고 싶은가요? – TalentTuner

+0

나는 당신이 원하는 것을 정확히 알아 내려고 노력하는 데 어려움을 겪고 있습니다. – poindexter12

+0

죄송합니다. 제 질문은 매우 모호합니다. 그냥 잠시 동안 객체에 액세스하는 방법입니다 (ReadNextElement()). p –

답변

16

나는 당신을 위해 무엇을 찾고있는 것이라고 생각합니다. 나는 쓰기 것 :

ReadItems()
List<DataObject> dataObject = source.ReadItems() 
            .TakeWhile(x => x.Category == "Category") 
            .ToList(); 

은 읽고 한 번에 하나 개의 항목을 산출 IEnumerable<DataObject>를 반환하는 방법이었다. iterator 블록 (yield return 등)을 사용하여 구현할 수도 있습니다.

다른 범주의 첫 번째 개체를 찾으면 곧바로 읽고 싶다고 가정합니다. 실제로 을 모두 포함하려는 경우 위의 LINQ 쿼리에서 DataObject, TakeWhile에서 Where으로 일치하는 모든이 포함됩니다.

(편집 : Saeed는 이후로 답변에 대한 이의 제기를 삭제했지만, 예를 들어 떠날 수도 있습니다.)

편집 :

using System; 
using System.Collections.Generic; 

public class DataObject 
{ 
    public string Category { get; set; } 
    public int Id { get; set; } 
} 

class Test 
{ 

    static int count = 0; 

    static DataObject ReadNextFile() 
    { 
     count++; 
     return new DataObject 
     { 
      Category = count <= 5 ? "yes" : "no", 
      Id = count 
     }; 
    } 

    static void Main() 
    { 
     List<DataObject> dataObjects = new List<DataObject>(); 

     DataObject nextObject; 
     while((nextObject = ReadNextFile()).Category == "yes") 
     { 
      dataObjects.Add(nextObject); 
     } 

     foreach (DataObject x in dataObjects) 
     { 
      Console.WriteLine("{0}: {1}", x.Id, x.Category); 
     } 
    } 
} 

출력 : 다음에 즉

1: yes 
2: yes 
3: yes 
4: yes 
5: yes 

, 목록이 그대로 남아 있습니다 참조 사이드가 날 믿어하지 않는 것 같은이, 작동합니다 증명 ReadNextFile에서 반환 된 5 개의 별개의 개체.

+0

Heya, 이건 정말이게 가장 좋은 해결책 인 것 같아. 그러나 한 가지가 있습니다. 내가 읽는 파일은 예외적으로 커질 수 있습니다 (몇 메가 바이트). 모든 항목을 선행 읽기, 그 perfomance 문제가 될 수 있을까요? –

3

이것은 주관적이지만이 패턴을 싫어합니다. (그리고 나는 여기에 아주 소수라는 것을 충분히 알고 있습니다.) 이런 식으로 내가 할 때 내가 어떻게하는지.

var dataObjects = new List<DataObject>(); 
while(true) { 
    DataObject obj = ReadNextFile(); 
    if(obj.Category != "category") { 
     break; 
    } 
    dataObjects.Add(obj); 
} 

그러나 이러한 일, GetItemsFromFile이 파일의 항목 path가 가리키는 읽고이를 IEnumerable<DataObject>를 반환 물론, 여기

List<DataObject> dataObjects = GetItemsFromFile(path) 
            .TakeWhile(x => x.Category == "category") 
            .ToList(); 

말을하는 것이 좋습니다.

+0

@Downvoter : 설명해주십시오. – jason

+0

나는 그게 문제가 아니기 때문에 너를 떨어 뜨렸다. –

+0

그리고 또한 나는 4 명의 downvoter가있다 그들 중의 1 명은 단지 이유를 말했다? 그들 중 누구도 그것을 제거하지 않습니다. –

3
List<DataObject> dataObjects = new List<DataObject>(); 
string category = ""; 

while((category=ReadNextFile().Category) == "category") 
{ 
    dataObjects.Add(new DataObject{Category = category}); 
} 

그리고 당신은 더 복잡한 개체를 경우 (존 등)이 작업을 수행 할 수 있습니다

List<DataObject> dataObjects = new List<DataObject>(); 
var category = new DataObject(); 

while((category=ReadNextFile()).Category == "category") 
{ 
    dataObjects.Add(category); 
} 
+0

Omg 너무 간단합니다 ... –

+1

@ 시드 : 죄송합니다, 내 이전 의견이 분명히 그것을하지 못했습니다 - 나는 이상한 3G 네트워크 연결에있어. 'List '에 문자열을 추가하려고하기 때문에 컴파일되지 않습니다. 아이디어는 마지막 * category *를 기억하는 것이 아니라 마지막'DataObject'를 기억하는 것입니다. 고정 버전에 대한 내 대답을 참조하십시오. –

+0

@ 존 스키트, 나는 답을 고쳤다. 고마워, 나는 OP만이 원하는 방식을 보여주고 싶다. –

0

당신은 클래스 컨테이너에 ReadNextFile에 대한 호출을 (를 IEnumerator 구현에 보일 것입니다). 그런 다음 IEnumerator.Current를 사용하여 현재 개체에 대한 참조를 항상 가질 수 있으며 MoveNext()는 승격 여부를 확인하기 위해 찾고있는 부울을 반환합니다. 이런 식으로 뭔가가 :

List<DataObject> dataObjects = new List<DataObject>(); 

DataObject nextObject; 
while((nextObject = ReadNextFile()).Category == "category") 
{ 
    dataObjects.Add(nextObject); 
} 

하지만 그렇게 할 것입니다 :

public class ObjectReader : IEnumerator<DataObject> 
{ 
    public bool MoveNext() 
    { 
     // try to read next file, return false if you can't 
     // if you can, set the Current to the returned DataObject 
    } 

    public DataObject Current 
    { 
     get; 
     private set; 
    } 
} 
+0

직접 구현하는 번거 로움이 전혀 필요하지 않습니다. 대신 iterator 블록을 사용하십시오. 그들은 바위 : –

+0

나는 그것이 필요하지 않는 것에 동의하지만, 그것이 그것이 (그 것처럼 보이는) 객체의 목적이라면, 그것은 더 우아한 해결책 IMO 인 것처럼 보입니다. – poindexter12

+0

@ poindexter12 : 전체 형식을 명시 적으로 만든 다음 반복기 블록을 사용하여 메서드를 작성하는 것보다 훨씬 우아합니다. 나는 두 가지 방법으로 완전한 해결책을 작성하고 다시 판단 해 보시기를 제안합니다 ... –

관련 문제