javascriptdictionaryobjectramda.js

JavaScript ramda map function with forEach


I wonder why ramda's map-function is not behaving as I would like i.e. 'dataAllAgesAllF' is an Object of more than 5 key-value pairs and I would like to choose only those key-value pairs that match the keys of 'ageGroupData'. The list line prints out nicely the 5 correct keys and the map-line works if I write explicitly x[ageGroupFNames[0]] instead of the arrow function

const ageGroupFNames = Object.keys(ageGroupData);
const dataAllAges5F = map((x) => [ageGroupFNames.forEach((FName) => x[FName])], dataAllAgesAllF);
ageGroupFNames.forEach((FName) => console.log(FName));

ageGroupData looks like this printed to console:

{F_team_ka: 7.3671186441, F_mult_ka: 6.3776666667, F_quic_ka: 6.3113333333, F_lang_ka: 5.9703333333, F_focu_ka: 5.9276666667}
F_focu_ka: 5.9276666667
F_lang_ka: 5.9703333333
F_mult_ka: 6.3776666667
F_quic_ka: 6.3113333333
F_team_ka: 7.3671186441
__proto__: Object

Currently dataAllAges5F prints out:

0: Array(1)
0: undefined
length: 1
__proto__: Array(0)
length: 1
__proto__: Array(0)

So I would like dataAllAges5F to look exactly like ageGroupData but with different numerical values there - actually, I finally would like to combine those two to plot with Billboard.js.


Solution

  • You can use the R.pick() method instead of map to return a subset of the dataAllAgesAllF object containing all the keys from the specified array (ie: the array of keys from your ageGroupData object):

    const dataAllAges5F = pick(keys(ageGroupData), dataAllAgesAllF);
    console.log(dataAllAges5F);  
    

    const ageGroupData = {F_team_ka: 7.3671186441, F_mult_ka: 6.3776666667, F_quic_ka: 6.3113333333, F_lang_ka: 5.9703333333, F_focu_ka: 5.9276666667};
    const dataAllAgesAllF = {foo: 1, bar: 1, baz: 1, qux: 1, F_team_ka: 2, F_mult_ka: 3, F_quic_ka: 4, F_lang_ka: 5, F_focu_ka: 6};
    
    const dataAllAges5F = pick(keys(ageGroupData), dataAllAgesAllF);
    console.log(dataAllAges5F);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js" integrity="sha256-buL0byPvI/XRDFscnSc/e0q+sLA65O9y+rbF+0O/4FE=" crossorigin="anonymous"></script>
    <script>const {keys, pick} = R;</script>

    Note: If a key from ageGroupData does not appear in dataAllAgesF, then it won't appear in the resulting object dataAllAges5F. If you want the key to appear and hold a value of undefined, you can use R.pickAll() instead.


    Since Ramda supports/focuses on functional-style methods, you can convert the above into a point-free function definition. The first step is to curry _.pick arguments:

    const dataAllAges5F = pick(keys(ageGroupData))(dataAllAgesAllF);
    

    Now we can remove the last passed in argument and use a function to pass that in instead (ie: eta-reduce the function):

    const pickByObj = pick(keys(ageGroupData)); // pickByObj(<object>) same as the above call
    

    Next step is to compose the above function call. We see that the above is in the form of f(g(x)), which can be re-written as f.g(x) - ie: a composed function:

    pick(keys(ageGroupData)); // Of the form f(g(x))
    ^-f  ^-g  ^-x
    

    To compose functions we can use the compose function:

    const pickByObj = compose(pick, keys)(ageGroupData); // Of the form (f.g)(x)
    

    Again, we can eta-reduce this to remove the ageGroupData:

    const pickByObj = compose(pick, keys);
    

    Now to call the above, you can pass through your two curried argument objects:

    const dataAllAges5F = pickByObj(ageGroupData)(dataAllAgesAllF);
    

    const ageGroupData = {F_team_ka: 7.3671186441, F_mult_ka: 6.3776666667, F_quic_ka: 6.3113333333, F_lang_ka: 5.9703333333, F_focu_ka: 5.9276666667};
    const dataAllAgesAllF = {foo: 1, bar: 1, baz: 1, qux: 1, F_team_ka: 2, F_mult_ka: 3, F_quic_ka: 4, F_lang_ka: 5, F_focu_ka: 6};
    
    const pickByObj = compose(pick, keys);
    console.log(pickByObj(ageGroupData)(dataAllAgesAllF));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js" integrity="sha256-buL0byPvI/XRDFscnSc/e0q+sLA65O9y+rbF+0O/4FE=" crossorigin="anonymous"></script>
    <script>const {compose, pick, keys} = R;</script>