5

前几天我有一个有趣的面试问题,我真的很挣扎。(非常雄心勃勃的)规范要求我用 C# 为两个不同的数据流编写解析器。这是第一个流的虚构示例:

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

其中 30 是货币对,35 是期限数,50、51、52 ​​分别是期限、买入价和卖出价。买价和卖价是可选的,但正确的价-卖价元组将至少具有两个价格中的一个。他们提供的框架代码暗示解析这一行的结果应该是 3 个单独的对象(DataElement 实例)。我最终得到了一个相当讨厌的 switch 语句和基于循环的实现,我不确定它是否真的有效。

有什么技术可以读取这种流?我试图用递归找出一些东西,但我做错了。

编辑:基于@evanmcdonnall 的回答(已接受),这里是完整的编译和工作代码,以防它对其他人有用。

        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();
    }

主要概念是:

  • 为每行中重复项目的“内循环”有一个单独的计数器
  • 有一个布尔标志来指示“内循环”何时开始
  • 分配对象数组以将“内循环”结果存储在长度已知的点(即标记 50)
  • 为了简单明了,有一个只读取一行的函数,然后从一个单独的函数中多次调用它。
4

2 回答 2

2

我看不出它有什么棘手的地方。但是,我没有看到任何解决方案比我想到的具有许多条件解决方案的非常具体的迭代更好。

首先你用逗号分割,然后循环遍历这些标记,用等号分割每个标记以获得键值对。当您开始/完成一个项目时,您可以检查每个键和一个 bool 来跟踪。您阅读货币并将其用于每个对象。您读取 key35并发现有 3 个对象,因此您分配了一个包含三个对象的数组,每个对象具有 3 个属性;男高音、出价和要价。当您遇到 50 时,您应该将 start 设置为 true。如果它们在那里,您设置 50、51 和 52。下面是一些示例代码;

  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.
  }

代码可能不漂亮,但逻辑相当简单,假设行格式正确,它将始终有效。

于 2013-04-22T22:05:37.543 回答
0

30=欧元/美元,35=3,50=开,51=12.5,52=13.5,50=6M,51=15.4,52=16.2,50=1Y,51=17.2,52=18.3

让我尝试。我不是在编写 C# 代码,只是概述我的方法

我会把它分成两段 Chain1={P0 , P1} 和 Chain2={P2......PN}

根据 P1 的值打破平均链 2。基于逗号的位置。

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

我们可以创建一个元组类集合——

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);
于 2013-04-22T22:07:16.787 回答