Efficient way to convert List of objects in a format for CSV class

37 Views Asked by At

I have a List of object of Tag type which is a my class inherited from SortedList<DateTime, T>. To allow add several Tag objects of different types (int, float, string), I created an interface called ITag. Tag objects can be have different sizes and different dates.

So I need to export this List of SortedList in a CSV file and my initial idea was to convert all tag object into a big SortedList<DateTime, List<string>> which it has like "Keys" all distinct tag dates and like "Values" a list of tags values in that specific time.

| 01/01/2024 00:01| 4, 6, "AAA" |

| 01/01/2024 00:02 | 2, , 8 |

I use a list for values because my CSV class accept a row of List<string>. That SortedList<DateTime, List<string>> take up huge memory and time to create, so I discared this method.

I thinked to delegate CSV class to "convert" my List of SortedList to CSV file getting a date one at thime with associate values founded and writing a single row. But I don't like that CSV class should be know how it's done Tag object or ITag object, it should be neutral taking a generic collection to elaborate.

public void Main()
{
    Tag<float?> m = new Tag<float?>();
    Tag<string?> o = new Tag<string?>();
    Tag<int?> d = new Tag<int?>();
    m.Add(new DateTime(2000, 1, 1), 1);
    o.Add(new DateTime(2000, 1, 1), 2);

    m.Add(new DateTime(2000, 1, 2), 4);
    o.Add(new DateTime(2000, 1, 3), "AAA");
    d.Add(new DateTime(2000, 1, 4), 6);
    d.Add(new DateTime(2000, 1, 5), null);
    d.Add(new DateTime(2000, 1, 1), 3);
    List<ITag> listTag = new(){ m, o,d };


    CSV? csvFile = new CSV(path, FileAccess.Write, CSVLocalCultureInfo);
    csvFile.WriteLocal(listTag);
}

public class CSV : IDisposable
{
    public void WriteLocal(List<ITag> listTag)
    {
        try
        {
            var dates = listTag.SelectMany(x => x.Keys).Distinct();
            int tagNum = listTag.Count;

            foreach (DateTime d in dates)
            {
                List<string?> tagValues = new(new string[tagNum]);
                for (int j = 0; j < tagNum; j++)
                {
                    object? value = null;
                    if (listTag[j].TryGetValue(d, out value))
                    {
                        tagValues[j] = value == null
                            ? "No Data"
                            : value.ToString().ToString(_nameCultureLocal).Replace("\n", "");
                    }
                }
                CreateRowLocal(d, tagValues);
            }
        }
        catch (Exception ex)
        {
            throw new FileException("Error");
        }
    }
}

public class Tag<T> : SortedList<DateTime, T?>, ITag, IEquatable<Tag<T>>
{
    bool ITag.TryGetValue(DateTime key, out object? value)
    {
        T? val = default;
        bool result = TryGetValue(key, out val);
        value = (object?)val;
        return result;
    }
}


public interface ITag : IEquatable<ITag>
{
    ...
    public bool TryGetValue(DateTime key, out object value);
    ...
}

For example, file destination should be:

Date Tag1 Tag2 Tag3
01/01/2024 00:00 2 AAA 6
01/01/2024 00:30 3 BBB No Data
... ... ... ...
0

There are 0 best solutions below