2013-04-22 38 views
5

Tôi đã có một câu hỏi phỏng vấn thú vị vào một ngày khác mà tôi thực sự gặp khó khăn. Đặc tả (tham vọng cao) yêu cầu tôi viết, trong C#, trình phân tích cú pháp cho hai luồng dữ liệu khác nhau. Dưới đây là ví dụ được tạo sẵn của luồng đầu tiên:Xử lý định dạng nguồn cấp dữ liệu

30=EUR/USD,35=3,50=ON,51=12.5,52=13.5,50=6M,51=15.4,52=16.2,50=1Y,51=17.2,52=18.3 

trong đó 30 là cặp tiền tệ, 35 là số lượng kỳ hạn và 50,51,52 là kỳ hạn, giá thầu và yêu cầu tương ứng. Giá thầu và yêu cầu là tùy chọn, nhưng một giá thầu tenor-bid-ask chính xác sẽ có ít nhất một trong hai giá. Mã khung mà họ cung cấp ngụ ý rằng kết quả phân tích cú pháp dòng này phải là 3 đối tượng riêng lẻ (các cá thể DataElement). Tôi đã kết thúc với một tuyên bố chuyển đổi khá khó chịu và thực hiện dựa trên vòng lặp mà tôi không chắc chắn thực sự làm việc.

Có những kỹ thuật nào để đọc loại luồng này? Tôi cố gắng tìm ra điều gì đó với đệ quy, điều mà tôi không thể làm đúng.

EDIT: Dựa trên câu trả lời của @ evanmcdonnall (được chấp nhận) ở đây là mã biên dịch và làm việc đầy đủ, trong trường hợp nó hữu ích cho bất kỳ ai khác.

 List<DataElement> Parse(string row) 
    { 
     string currency=string.Empty; 
     DataElement[] elements = null; 
     int j = 0; 
     bool start = false; 
     string[] tokens = row.Split(','); 
     for (int i = 0; i < tokens.Length; i++) 
     { 
      string[] kv = tokens[i].Split('='); 

      switch (kv[0]) 
      { 
       case "30": 
        currency = kv[1]; 
        break; 
       case "35": 
        elements = new DataElement[int.Parse(kv[1])]; 
        break; 
       case "50": 
        if (start) 
         j++; 
        elements[j] = new DataElement() { currency = currency, tenor = kv[1] }; 
        start = true; 
        break; 
       case "51": 
        elements[j].bid = double.Parse(kv[1]); 
        break; 
       case "52": 
        elements[j].ask = double.Parse(kv[1]); 
        break; 
      } 
     } 
     return elements.ToList(); 
    } 

Các khái niệm chính là:

  • Có một quầy riêng cho "vòng trong" lặp lại các mục trong mỗi dòng
  • Có một lá cờ boolean để cho biết khi đó "vòng trong" bắt đầu
  • Phân bổ mảng đối tượng để lưu trữ kết quả "vòng lặp bên trong" tại điểm mà độ dài được biết (nghĩa là, thẻ 50)
  • Để đơn giản và rõ ràng, có chức năng chỉ đọc một lần , sau đó gọi nó nhiều lần từ một hàm riêng biệt.
+0

Nó không giống như thế này là một luồng dữ liệu xác định, cũng không chiều rộng cố định. Tôi nghĩ phương pháp của bạn có vẻ hợp lý –

+0

là thứ tự của các phần tử luôn giống nhau? Ý tôi là trước tiên bạn sẽ có cặp tiền tệ, sau đó là số lượng kỳ hạn, và sau đó số lượng chính xác các bộ dữ liệu tương ứng với số lượng kỳ hạn? – ppetrov

+1

@AndrewWalters: Có vẻ như được phân cách khá nhất quán với ',' ... – mellamokb

Trả lời

2

Tôi không thấy điều gì phức tạp đến vậy. Tuy nhiên, tôi không thấy bất kỳ giải pháp nào có thể tốt hơn rất nhiều, lặp lại với nhiều giải pháp có điều kiện mà tôi có trong đầu.

Trước tiên, bạn phân tách trên dấu phẩy, sau đó bạn lặp lại các mã thông báo đó, chia từng dấu trên dấu bằng để lấy cặp giá trị khóa. Bạn có kiểm tra cho mỗi khóa và một bool để theo dõi khi bạn bắt đầu/kết thúc một mục. Bạn đọc tiền tệ và sử dụng tiền đó cho từng đối tượng. Bạn đọc khóa 35 và tìm thấy có 3 đối tượng, do đó bạn phân bổ một mảng ba đối tượng, mỗi đối tượng có 3 thuộc tính; tenor, bid, và ask. Khi bạn gặp 50 bạn nên thiết lập một sự khởi đầu của bạn đúng sự thật. Bạn đặt 50, 51 và 52 nếu chúng ở đó. Dưới đây là một số mã mẫu;

string currency; 
    int j = 0; 
    bool start = false; 
    string[] tokens = line.Split(','); 
    for (int i =0; i < tokens.length; i++) 
    { 
     string[] kv = tokens[i].Split('=') 
     if (kv[0] == 30) 
      currency = kv[1] 
     elseif (kv[0] == 35) 
     { 
      DateElement[] elements = new DataElement[kv[1]]; 
     } 
     elseif (kv[0] == 50) 
     { 
      if (start) 
       j++; 
      start = true; // flip your flag after the condition so it works for element 0 
      elements[j].currency = currency; 
      elements[j].tenor = kv[1]; 
     } 
     elseif (kv[0] == 51) 
      elements[j].bid = kv[1]; 
     elseif (kv[0] == 52)  
      elements[j].ask = kv[1]; 
     // if these optional values aren't there we'll just fall back into the case for 50 
     // and everything will work as expected. 
    } 

Mã có thể không đẹp, nhưng logic là khá tầm thường và giả định định dạng đường là chính xác, nó sẽ luôn hoạt động.

+1

Tôi đã không nói nó là khó khăn, tôi nói tôi đấu tranh với nó - có một sự khác biệt rất rõ ràng giữa hai báo cáo :). Tôi thấy rằng loại mã của bạn theo sau dòng tôi đã lấy, ngoại trừ việc bạn có một biến đếm riêng biệt (j) trong khi tôi cố gắng kết hợp của tôi với biến vòng lặp (i) và cách tiếp cận phân bổ mảng phần tử khi thẻ 35 đến là một trong những tốt đẹp. Cảm ơn. – endian

+0

@endian lời xin lỗi của tôi. Loại xử lý chuỗi này hơi khó lúc đầu nhưng sau khi bạn quen với nó, nó trở nên rất thường xuyên. – evanmcdonnal

+0

Bạn có cần đặt biến 'j' của mình về 0 khi bạn nhận được 35 = mới không? – endian

0

30 = EUR/USD, 35 = 3,50 = ON, 51 = 12.5,52 = 13.5,50 = 6M, 51 = 15,4,52 = 16,2,50 = 1Y, 51 = 17.2,52 = 18.3

Hãy để tôi thử. Tôi không viết code C#, chỉ cần đưa ra một cái nhìn tổng quan về cách tiếp cận của tôi

tôi sẽ phá vỡ này thành 2 phân khúc Chain1 = {P0, P1} và Chain2 = {P2 ...... PN}

nghỉ chuỗi đồng đều 2 dựa trên giá trị từ P1. dựa trên vị trí của dấu phẩy.

substr=Chain.substring(0,Chain2.IndexOf(",", P1=3)); 

Chúng ta có thể tạo ra một Bộ sưu tập Tuple Class -

here either i can use regex to split the string or simple substring and indexof("=") to extract value 

var seg= new Tuple<string, int, int, >("ON", 12.5, 13.5); 
Các vấn đề liên quan