Как объединить / сжать универсальные списки разных типов (и привести результат в словарь)? - PullRequest
0 голосов
/ 18 августа 2011

Мне нужно прочитать данные из некоторых листов Excel.Данные в таблицах Excel уже отформатированы таким образом, что я могу получить нужные данные с помощью этого метода.

Вот что я делаю:

using (var conn = new OleDbConnection(strBld.ToString()))
{
    conn.Open();

    IEnumerable<IDictionary<string, object>> excelDataRaw = 
        conn.Query("select * from [Curves$A:IT]").
        Cast<IDictionary<string, object>>();

    int i = 0;
    string previousKey = null;
    var curve = new List<IEnumerable<object>>();
    var excelData = new Dictionary<string, IDictionary<object, object>>();
    //var excelData = new Dictionary<string, IDictionary<string, decimal>>();

    foreach (var key in excelDataRaw.Select(dictionary => dictionary.Keys).
        ElementAt(i))
    {
        string key1 = key;
        // gets the data from one column within the excel file
        curve.Add(excelDataRaw.Select(col => col[key1]).
            Where(row => row != null).ToList());

        if (i % 2 == 0)
        {
            // store the column header
            previousKey = key;
        }

        if (i % 2 == 1)
        {
            // merge the data from the first column (keys)
            // with the data from the second column (values)
            IEnumerable<object> keys = curve[i - 1];
            IEnumerable<object> values = curve[i];
            // cast works but than you can't zip the lists together
            //IEnumerable<string> keys = curve[i - 1].Cast<string>();
            //IEnumerable<decimal> values = curve[i].Cast<decimal>();

            // zip them together on their index
            var dic = keys.Zip(values, (k, v) => new { k, v }).
                ToDictionary(x => x.k, x => x.v);

            if (previousKey != null)
            {
                if (!excelData.ContainsKey(previousKey))
                {
                    excelData.Add(previousKey, dic);
                }
            }
        }

        ++i;
    }
}

Iизвлечь все данные из файла Excel (excelDataRaw).Затем я выбираю все данные, которые принадлежат друг другу, в список (кривую) и объединяет два списка, которые принадлежат друг другу, в словарь (dic).Конечный результат - это словарь (excelData), который содержит заголовок столбца из файла excel в качестве ключа (previousKey) и данные, относящиеся к этому заголовку столбца в виде словаря (dic).

Я хотел бы привестисловарь (excelData) из

Dictionary<string, IDictionary<object, object>> 

в

Dictionary<string, IDictionary<string, decimal>> 

, но я не могу привести объект к строковому или десятичному типу и не могу сжать списки вместе, чтобы получить словарь (dic) после приведения каждого списка к нужному типу.Кто-нибудь знает, как добиться желаемого результата (типа)?

Ответы [ 2 ]

1 голос
/ 18 августа 2011

ExcelDataRaw имеет тип Dictionary<string, IDictionary<object, object>>, поэтому ему нужно IDictionary<object, object> в качестве значения. Вы не можете преобразовать Dictionary<string,decimal> в IDictionary<object,object>, потому что IDictionary не является ковариантным интерфейсом - см. http://msdn.microsoft.com/en-us/library/dd469487.aspx.

Решение состоит в том, чтобы либо изменить тип ExcelDataRaw на Dictionary<string, IDictionary<string, decimal>>, либо оставить его как есть, и при попытке использовать значения из этого словаря приведите их к правильным типам:

foreach(var kv in ExcelDataRaw)
{
   Dictionary<string,decimal> convertedValue=kv.Value.ToDictionary(x=>(string)x.Key,x=>(decimal)x.Value);
   // or convert it even further down the road
   string lookup = "abc";
   decimal v = (decimal)kv.Value[lookup];
}
0 голосов
/ 19 августа 2011

Ну, я нашел решение, должно быть, я упустил очевидное вчера.Иногда помогает хороший ночной сон:).

IEnumerable<object> keys = curve[i - 1];
IEnumerable<object> values =
    curve[i].Where(content => decimal.TryParse(content.ToString(), out num));
    Dictionary<string, decimal> dic =
        keys.Zip(values, (k, v) => new { k, v }).ToDictionary(
            x => (string)x.k, x => decimal.Parse(x.v.ToString()));
if (previousKey != null)
{
    if (!excelData.ContainsKey(previousKey))
    {
        excelData.Add(previousKey, dic);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...