Wednesday 15 July 2015

c# - Formatting and getting missing data -



c# - Formatting and getting missing data -

i'm beginner in c#. have info construction resourceid, editionid, locationid, viewcount, , clickcount. each entry has date , information. shown in next image.

in days may different editionid, resourcesid,viewcount,clickcount same resourceid

i have next var enteries = new dictionary<igaadkey, igaentry>(); igaadkey has resourceid,locationid,editionid. igaentry has viewcount , clickcount.

i have hashset<int> of resources there. have dictionary<string, hashset<int>> resourcesdate day -> resources ids available in day, can set empty places in row, if there resourceid in current processing date not in date, set in row, empty places.

using information, format table, still have problems in populating info correctly. row in wrong place,..etc

the code utilize populate data:

foreach (igaadkey adkey in enteries.keys) { igaentry entry; if (enteries.trygetvalue(adkey, out entry)) { streamwriter.write(adkey.locationid + ","); streamwriter.write(adkey.editionid + ","); streamwriter.write(entry.mclickcount + ","); streamwriter.write(entry.mviewcount + ","); streamwriter.write(","); } else { (int = 0; < 5; i++) { streamwriter.write(","); } } }

update:

the code shown never output empty line. that's because loop though keys of enteries dictionary, seek value key. value found, since you're looping through keys. improve loop through dictionary collection of keyvaluepair<tkey, tvalue> objects.

there very similar question asked earlier problem grouping dictionary entries same resourceid different values editionid or locationid. assuming same issue, 1 way create igaadkey implement icomparable<igaadkey> so:

public class igaadkey : iequatable<igaadkey>, icomparable<igaadkey> { public int resourceid; public int editionid; public int locationid; public override bool equals(object obj) { if (referenceequals(this, obj)) homecoming true; else if (referenceequals(null, obj)) homecoming false; if (obj.gettype() != gettype()) homecoming false; var other = (igaadkey)obj; homecoming resourceid == other.resourceid && editionid == other.editionid && locationid == other.locationid; } public override int gethashcode() { homecoming resourceid.gethashcode() ^ editionid.gethashcode() ^ locationid.gethashcode(); } public override string tostring() { homecoming string.format("resourceid={0}, editionid={1}, locationid={2}", resourceid, editionid, locationid); } #region iequatable<igaadkey> members public bool equals(igaadkey other) { homecoming equals((object)other); } #endregion #region icomparable<igaadkey> members public int compareto(igaadkey other) { if (other == null) homecoming -1; // @ end? if (object.referenceequals(this, other)) homecoming 0; int diff; if ((diff = resourceid.compareto(other.resourceid)) != 0) homecoming diff; if ((diff = editionid.compareto(other.editionid)) != 0) homecoming diff; if ((diff = locationid.compareto(other.locationid)) != 0) homecoming diff; homecoming 0; } #endregion }

having done this, can either:

store objects in sorteddictionary:

var enteries = new sorteddictionary<igaadkey, igaentry>() // build dictionary foreach (var pair in enteries) { // write csv file }

in case keys identical resourceid adjacent.

store them in regular dictionary , sort them writing:

var enteries = new dictionary<igaadkey, igaentry>() // build dictionary foreach (var pair in enteries.orderby(pair => pair.key)) { // write csv file }

incidentally, if going using igaadkey dictionary key, should create immutable, reasons discussed here.

update

although question isn't clear, code able determine trying output table 2d grid of smaller tables. along x axis resource ids, 5 columns of info each. along y axis dates, , each date, many rows needed each location & edition found each resource + date combination.

in case, need to:

collect files , index them date (you doing that).

scan through files find resource ids (you doing that).

sort list of resources consistent order, output of programme not random in way:

var allresourcesinorder = allresources.tolist(); allresourcesinorder.sort();

output 5 columns each resource:

foreach (int resourceid in allresourcesinorder) { stream.write(resourceid + ","); stream.write("location id" + ","); stream.write("edition id" + ","); stream.write("click count" + ","); stream.write("view count" + ","); } stream.write("\n");

for each date, output cells each resource found date in files found date:

/// <summary> /// reads & merges files 1 specific date , create iga entry, merge values, write them file /// </summary> /// <param name="date"></param> /// <param name="files"></param> /// <param name="streamwriter"></param> private static void readmergeandwritefilesforday( datetime date, list<string> files, streamwriter streamwriter, ilist<int> allresourcesinorder // specifies column order. ) { var enteries = new dictionary<igaadkey, igaentry>(); foreach (string filename in files) readfileforday(filename, enteries); var dateresources = new dictionary<int, list<igaadkey>>(); foreach (var key in enteries.keys) dateresources.add(key.resourceid, key); // sort resources output them in consistent order. not required practice. dateresources.sortall(); (int irow = 0, nrows = dateresources.maxcount(); irow < nrows; irow++) { (int index = 0; index < allresourcesinorder.count; index++) { if (index == 0) streamwriter.write(date.todatestring() + ","); else streamwriter.write(","); // date goes under resource id first resource; otherwise leave empty. int resourceid = allresourcesinorder[index]; igaadkey key; igaentry value; if (dateresources.trygetvalue(resourceid, irow, out key) && enteries.trygetvalue(key, out value)) { streamwriter.write(key.locationid + ","); streamwriter.write(key.editionid + ","); streamwriter.write(value.mclickcount + ","); streamwriter.write(value.mviewcount + ","); } else { streamwriter.write(","); streamwriter.write(","); streamwriter.write(","); streamwriter.write(","); } } } }

note readfileforday extracted first half of mergefilesforday, here.

add few useful extension methods create life easier:

public static class returns { public static bool false<tvalue>(out tvalue value) { value = default(tvalue); homecoming false; } } public static class listdictionaryextensions { public static void add<tkey, tvalue>(this idictionary<tkey, list<tvalue>> listdictionary, tkey key, tvalue value) { if (listdictionary == null) throw new argumentnullexception(); list<tvalue> values; if (!listdictionary.trygetvalue(key, out values)) { listdictionary[key] = (values = new list<tvalue>()); } values.add(value); } public static bool trygetvalue<tkey, tvalue>(this idictionary<tkey, list<tvalue>> listdictionary, tkey key, int index, out tvalue value) { list<tvalue> list; if (!listdictionary.trygetvalue(key, out list)) homecoming returns.false(out value); if (index < 0 || index >= list.count) homecoming returns.false(out value); value = list[index]; homecoming true; } public static void sortall<tkey, tvalue>(this idictionary<tkey, list<tvalue>> listdictionary) { if (listdictionary == null) return; foreach (var list in listdictionary.values) list.sort(); } public static int maxcount<tkey, tvalue>(this idictionary<tkey, list<tvalue>> listdictionary) { if (listdictionary == null) homecoming 0; int count = 0; foreach (var list in listdictionary.values) count = math.max(count, list.count); homecoming count; } }

full code here. of course of study can't test since don't have of input files.

c# algorithm sorting csv

No comments:

Post a Comment