Transforming a Map using map()


#1

Hi there, I was trying to use the function map() to apply a function and create a new container (transforming a Map to a different (new) Map). I wasn’t able to do it…is there a way? Here’s what I was trying:

    auto testMap = ["hello": 5.3, "there": 10];

    // for_each() works fine on a Map
    testMap.for_each(fun(kvPair) { print("${kvPair.first} : ${kvPair.second}") });
    // --> hello : 5.3
    // --> there : 10

    // ...but map() doesn't seem to allow you to create/return a new Map
    auto convertedMap;
    try {
        convertedMap = testMap.map(fun(kvPair) { return Pair(kvPair.first, kvPair.second * 100); });
    }
    catch (e) {
        print("${e.what()}");
        // --> Error: "Error with function dispatch with function 'inserter'" With parameters: (Map, Pair) 
    }
    
    // Neither does insert() seem to work on a Map, even using Map_Pair keys taken exactly from another Map
    convertedMap = Map();
    try {
        for (kvPair : testMap) {
            convertedMap.insert(kvPair);
        }
    }
    catch (e) {
        print("${e.what()}");
        // --> Error: "Error with function dispatch for function 'insert'" With parameters: (Map).(Map_Pair) 
    }

    // This style of "indexed" addition does work, though.
    for (kvPair : testMap) {
        convertedMap[kvPair.first] = kvPair.second * 100;
    }
    print("convertedMap: ${convertedMap}");
    // --> convertedMap: [<hello, 530>, <there, 1000>]

I was hoping to be able to write transformer functions and apply them to Maps using map(). I can use the last approach above as a workaround, but just wondering if it’s possible to do it directly? Is there a way I can specify an “inserter” so it works?

Thanks,
Glen.


#2

If anyone’s interested, the following works as a workaround for what I was trying to do:

// map() a Map, applying valueFunc() to each value while keeping the keys
// the same and returning the results in a new Map.
def mapValues(m, valueFunc) {
    auto newMap = Map();
    for (kvPair : m) {
        newMap[kvPair.first] = valueFunc(kvPair.second);
    }
    return newMap;
}

// Workaround to use map() on Map values
auto testMap = ["hello": 5.3, "there": 10];
auto convertedMap = testMap.mapValues(fun(x) { x * 0.05 });
print("convertedMap (* 0.05): ${convertedMap}");
// --> convertedMap (* 0.05): [<hello, 0.265>, <there, 0.5>]