4

I have two arrays with the same length and I need to use the first as a Key and the second as a Value.

My Key is an unique string and my Value is a double. I have 6 capybaras. Their names will be the key and their weight is the pound.

My current code:

        ViewBag.MeuBalaioDeCapivaras = new string[]
        {
            "Jerimúndia",
            "Genoveva",
            "Facibulana",
            "Carnavala",
            "Dentinhos Dourados",
            "Creusa"
        };

        ViewBag.PesoDeCadaCapivaraDoMeuBalaioDeCapivaras = new double[]
        {
            500.0,
            400.0,
            250.0,
            12.0,
            1589.0,
            87.3
        };

This is my Arrays and I was doing as a KeyValuePair:

var keyValuePair = new KeyValuePair<string, double>(ViewBag.NomeDaCapivara, ViewBag.PesoDeCadaCapivaraDoMeuBalaioDeCapivaras);

It compiles perfectly, but in the end it gives me an exception, when running:

=> An exception of type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in System.Core.dll but was not handled in user code. Additional information: The best correspondence of the overloaded method.

How can I do what I need?

Felipe Oriani
  • 37,948
  • 19
  • 131
  • 194
Marcelo Camargo
  • 2,240
  • 2
  • 22
  • 51

2 Answers2

12

LINQ has a little-known function to do just that - Zip. The function takes two collections and merges them into a single collection:

int[] numbers = { 1, 2, 3, 4 };
string[] words = { "one", "two", "three" };

var numbersAndWords = numbers.Zip(words, (number, word) => new KeyValuePair<string,int>(word, number);
Avner Shahar-Kashtan
  • 14,492
  • 3
  • 37
  • 63
1

Your code compiles because ViewBag is dynamic, this means there is no compile time checking.

If you replaced

var keyValuePair = new KeyValuePair<string, double>(ViewBag.NomeDaCapivara, ViewBag.PesoDeCadaCapivaraDoMeuBalaioDeCapivaras);

If you put the arrays in directly, you would get the compile time error you are expecting: e.g.

var keyValuePair = new KeyValuePair<string, double>(
    new string[] { "Jerimúndia", "Genoveva", "Facibulana", "Carnavala", "Dentinhos Dourados", "Creusa" },
new double[] { 500.0, 400.0, 250.0, 12.0, 1589.0, 87.3 });

Gives:

Compilation error (line x1, col y1): The best overloaded method match for 'System.Collections.Generic.KeyValuePair<string,double>.KeyValuePair(string, double)' has some invalid arguments
Compilation error (line x2, col y2): Argument 1: cannot convert from 'string[]' to 'string'
Compilation error (line x3, col y3): Argument 2: cannot convert from 'double[]' to 'double'

The old school, explicit way to do this would be something like:

    var meuBalaioDeCapivaras = new string[]
    {
    "Jerimúndia", "Genoveva", "Facibulana", "Carnavala", "Dentinhos Dourados", "Creusa"
    };

    var pesoDeCadaCapivaraDoMeuBalaioDeCapivaras = new double[]
    {
    500.0, 400.0, 250.0, 12.0, 1589.0, 87.3
    };

    var list = new List<KeyValuePair<string, double>>();

    for (var i = 0; i < meuBalaioDeCapivaras.Length; i++)
    {
        list.Add(new KeyValuePair<string, double>(meuBalaioDeCapivaras[i], pesoDeCadaCapivaraDoMeuBalaioDeCapivaras[i]));
    }

As Felipe Oriani and Avner Shahar-Kashtan have stated, if you are using .NET 3.5 or above, you can use Linq

Community
  • 1
  • 1
BanksySan
  • 27,362
  • 33
  • 117
  • 216
  • would this cause an issue if the lengths are not checked, since the expected types for the KeyValuePair are not nullable, or no? – Brett Weber Jul 30 '14 at 19:24
  • @BrettWeber Yes, it would. You should also check the types coming out of the `ViewBag` as well. What if you called `.Remove()` and it turned out to be a repository, rather than a list? – BanksySan Jul 30 '14 at 19:32
  • hrm.. Ok, that helped out! I used linq for my attempts at a similar behavior, but if this is faster than my implementation, I'll be able to avoid those pitfalls whenever I get around to updating it. Thanks! – Brett Weber Jul 30 '14 at 20:12