September 29, 2020

Extension methods to Convert Strings to Various Fundamental types

These extension methods converts strings to various types (int, bool, float)
When the string is invalid they return a fallback value.
public static class StringParserExtensions
{
	public static int ParseInt(this string part, int fallbackValue = 0)
	{
		if (!int.TryParse(part.Trim(), out int anInt))
		{
			anInt = fallbackValue;
		}
		return anInt;
	}

	public static bool ParseBool(this string part, bool fallbackValue = false)
	{
		if (!bool.TryParse(part.Trim(), out bool aBool))
		{
			aBool = fallbackValue;
		}
		return aBool;
	}

	public static float ParseFloat(this string part, float fallbackValue = 0.0f)
	{
		if (!float.TryParse(part.Trim(), out float number))
		{
			number = fallbackValue;
		}
		return number;
	}
}
Example usage:
  stationLocation.StationId = parts[0].ParseInt(0); 

Linq GroupBy/ToLookUp

These are Linq methods to group elements in a sequence. ToLookup() is the same as GroupBy(); the only differences are that GroupBy execution is deferred, whereas ToLookup() execution is immediate and also ToLookup() is not available in linq query form only the method form.

Note that the resultant group object exposes itself in 2 ways:

1. A 'Key' property exposes a value which all the items in the group have in common (this could be a calculated value)

2. The group object itself is an IEnumerable of the items in the group.

This operation will iterate over all the items in the enumeration. Works well with the Linq method "ToDictionary()" to convert a sequence into a dictionary.

Here is an example:

// Read StationLocationRaw(s) (int StationId and string Location)
// from the Station Locations file
public class StationLocationReader 
{
    FileInfo fi;
    public StationLocationReader(string path)
    {
        fi = new FileInfo(path);
    }

    public IDictionary<int, string> StationLocationsByStationId()
    {
        var stationLocationsDictionary =
            ReadStationLocations(). // returns StationLocationRaw(s)
                                    // (int StationId and string Location)
            GroupBy(s => s.StationId).
            ToDictionary(g => g.Key, g => g.Single().Location ?? "");
        return stationLocationsDictionary;
    }

    public IEnumerable<StationLocationRaw> ReadStationLocations()
    {
        Debug.Assert(fi.Exists);
        var stationLocations = fi.
            ReadLines().
            Skip(1). // Skip the header line
            Select(line => ExtractStationLocation(line));
        return stationLocations;
    }

    private StationLocationRaw ExtractStationLocation(string line)
    {
        var stationLocation = new StationLocationRaw();
        var parts = line.Split('\t');
        if (parts.Length >= 2)
        {
            // ParseInt is an extension method to convert
            // to a string to an integer, returning 0 
            // when the string is invalid.
            stationLocation.StationId = parts[0].Trim().ParseInt(0); 
            stationLocation.Location = parts[1].Trim();
        }
        return stationLocation;
    }
}