Posts in  considerations

9.24.2013

Map Then Collect

Iterating through a collection of data and mapping to a new type is a rather routine development task. Here are various ways to do this. At the bottom I have a list of things to consider. What conclusions do you come to?

Note: in LINQ the map operator is named Select

Mapping

for Loop

public List<Output> ForLoop()
{
    var outputs = new List<Output>();
    var inputs = GetInputs();
    for (var i = 0; i < inputs.Count(); i++)
    {
        var input = inputs[i];
        var output = new Output();
        output.Id = Convert.ToInt32(input.Id);
        outputs.Add(output);
    }
    return outputs;
}

foreach Loop

public List<Output> ForEachLoop()
{
    var outputs = new List<Output>();
    foreach (var input in GetInputs())
    {
        var output = new Output();
        output.Id = Convert.ToInt32(input.Id);
        outputs.Add(output);
    }
    return outputs;
}

Functional ForEach

public List<Output> FunctionalForEachLoop()
{
    var outputs = new List<Output>();
    GetInputs()
        .ForEach(input => MapAndAdd(input, outputs));
    return outputs;
}

private void MapAndAdd(Input input, List<Output> outputs)
{
    var output = new Output();
    output.Id = Convert.ToInt32(input.Id);
    outputs.Add(output);
}

Functional Map Then Collect

public List<Output> FunctionalMapThenCollect()
{
    var outputs = GetInputs()
        .Select(input =>
        {
            var output = new Output();
            output.Id = Convert.ToInt32(input.Id);
            return output;
        })
        .ToList();
    return outputs;
}

Functional Constructor Map Then Collect

public List<Output> FunctionalConstructorMapThenCollect()
{
    var outputs = GetInputs()
        .Select(input => new Output(input))
        .ToList();
    return outputs;
}

Adding Filtering

foreach With Filter

public List<Output> ForEachWithFilter()
{
    var outputs = new List<Output>();
    foreach (var input in GetInputs())
    {
        int id;
        if (!Int32.TryParse(input.Id, out id))
        {
            continue;
        }

        var output = new Output();
        output.Id = id;
        outputs.Add(output);
    }
    return outputs;
}

Functional Map Then Filter Then Collect

public List<Output> FunctionalMapThenFilterThenCollect()
{
    var outputs = GetInputs()
        .Where(InputHasValidId)
        .Select(input => new Output(input))
        .ToList();
    return outputs;
}

private bool InputHasValidId(Input input)
{
    int id;
    return Int32.TryParse(input.Id, out id);
}

Considerations

  • Readable
  • Understanding / Confusing
  • Composition
  • Extensible
  • Intent
  • What is explicit?
  • What is implicit?

For reference

public class Input
{
    public string Id { get; set; }
}

public class Output
{
    public Output()
    {
    }

    public Output(Input input)
    {
        Id = Convert.ToInt32(input.Id);
    }

    public int Id { get; set; }
}