map function for objects (instead of arrays)

前端 未结 30 1921
无人及你
无人及你 2020-11-22 04:23

I have an object:

myObject = { \'a\': 1, \'b\': 2, \'c\': 3 }

I am looking for a native method, similar to Array.prototype.map

相关标签:
30条回答
  • 2020-11-22 05:00

    If you're interested in mapping not only values but also keys, I have written Object.map(valueMapper, keyMapper), that behaves this way:

    var source = { a: 1, b: 2 };
    function sum(x) { return x + x }
    
    source.map(sum);            // returns { a: 2, b: 4 }
    source.map(undefined, sum); // returns { aa: 1, bb: 2 }
    source.map(sum, sum);       // returns { aa: 2, bb: 4 }
    
    0 讨论(0)
  • 2020-11-22 05:01

    It's pretty easy to write one:

    Object.map = function(o, f, ctx) {
        ctx = ctx || this;
        var result = {};
        Object.keys(o).forEach(function(k) {
            result[k] = f.call(ctx, o[k], k, o); 
        });
        return result;
    }
    

    with example code:

    > o = { a: 1, b: 2, c: 3 };
    > r = Object.map(o, function(v, k, o) {
         return v * v;
      });
    > r
    { a : 1, b: 4, c: 9 }
    

    NB: this version also allows you to (optionally) set the this context for the callback, just like the Array method.

    EDIT - changed to remove use of Object.prototype, to ensure that it doesn't clash with any existing property named map on the object.

    0 讨论(0)
  • 2020-11-22 05:01

    First, convert your HTMLCollection using Object.entries(collection). Then it’s an iterable you can now use the .map method on it.

    Object.entries(collection).map(...)
    

    reference https://medium.com/@js_tut/calling-javascript-code-on-multiple-div-elements-without-the-id-attribute-97ff6a50f31

    0 讨论(0)
  • 2020-11-22 05:01

    A different take on it is to use a custom json stringify function that can also work on deep objects. This might be useful if you intend to post it to the server anyway as json

    const obj = { 'a': 1, 'b': 2, x: {'c': 3 }}
    const json = JSON.stringify(obj, (k, v) => typeof v === 'number' ? v * v : v)
    
    console.log(json)
    console.log('back to json:', JSON.parse(json))

    0 讨论(0)
  • 2020-11-22 05:03

    I specifically wanted to use the same function that I was using for arrays for a single object, and wanted to keep it simple. This worked for me:

    var mapped = [item].map(myMapFunction).pop();
    
    0 讨论(0)
  • 2020-11-22 05:04

    My response is largely based off the highest rated response here and hopefully everyone understands (have the same explanation on my GitHub, too). This is why his impementation with map works:

    Object.keys(images).map((key) => images[key] = 'url(' + '"' + images[key] + '"' +    
    ')');
    

    The purpose of the function is to take an object and modify the original contents of the object using a method available to all objects (objects and arrays alike) without returning an array. Almost everything within JS is an object, and for that reason elements further down the pipeline of inheritance can potentially technically use those available to those up the line (and the reverse it appears).

    The reason that this works is due to the .map functions returning an array REQUIRING that you provide an explicit or implicit RETURN of an array instead of simply modifying an existing object. You essentially trick the program into thinking the object is an array by using Object.keys which will allow you to use the map function with its acting on the values the individual keys are associated with (I actually accidentally returned arrays but fixed it). As long as there isn't a return in the normal sense, there will be no array created with the original object stil intact and modified as programmed.

    This particular program takes an object called images and takes the values of its keys and appends url tags for use within another function. Original is this:

    var images = { 
    snow: 'https://www.trbimg.com/img-5aa059f5/turbine/bs-md-weather-20180305', 
    sunny: 'http://www.cubaweather.org/images/weather-photos/large/Sunny-morning-east-   
    Matanzas-city- Cuba-20170131-1080.jpg', 
    rain: 'https://i.pinimg.com/originals/23/d8
    /ab/23d8ab1eebc72a123cebc80ce32b43d8.jpg' };
    

    ...and modified is this:

    var images = { 
    snow: url('https://www.trbimg.com/img-5aa059f5/turbine/bs-md-weather-20180305'),     
    sunny: url('http://www.cubaweather.org/images/weather-photos/large/Sunny-morning-   
    east-Matanzas-city- Cuba-20170131-1080.jpg'), 
    rain: url('https://i.pinimg.com/originals/23/d8
    /ab/23d8ab1eebc72a123cebc80ce32b43d8.jpg') 
    };
    

    The object's original structure is left intact allowing for normal property access as long as there isn't a return. Do NOT have it return an array like normal and everything will be fine. The goal is REASSIGNING the original values (images[key]) to what is wanted and not anything else. As far as I know, in order to prevent array output there HAS to be REASSIGNMENT of images[key] and no implicit or explicit request to return an array (variable assignment does this and was glitching back and forth for me).

    EDIT:

    Going to address his other method regarding new object creation to avoid modifying original object (and reassignment appears to still be necessary in order to avoid accidentally creating an array as output). These functions use arrow syntax and are if you simply want to create a new object for future use.

    const mapper = (obj, mapFn) => Object.keys(obj).reduce((result, key) => {
                    result[key] = mapFn(obj)[key];
                    return result;
                }, {});
    
    var newImages = mapper(images, (value) => value);
    

    The way these functions work is like so:

    mapFn takes the function to be added later (in this case (value) => value) and simply returns whatever is stored there as a value for that key (or multiplied by two if you change the return value like he did) in mapFn(obj)[key],

    and then redefines the original value associated with the key in result[key] = mapFn(obj)[key]

    and returns the operation performed on result (the accumulator located in the brackets initiated at the end of the .reduce function).

    All of this is being performed on the chosen object and STILL there CANNOT be an implicit request for a returned array and only works when reassigning values as far as I can tell. This requires some mental gymnastics but reduces the lines of code needed as can be seen above. Output is exactly the same as can be seen below:

    {snow: "https://www.trbimg.com/img-5aa059f5/turbine/bs-   
    md-weather-20180305", sunny: "http://www.cubaweather.org/images/weather-
    photos/l…morning-east-Matanzas-city-Cuba-20170131-1080.jpg", rain: 
    "https://i.pinimg.com/originals/23/d8
    /ab/23d8ab1eebc72a123cebc80ce32b43d8.jpg"}
    

    Keep in mind this worked with NON-NUMBERS. You CAN duplicate ANY object by SIMPLY RETURNING THE VALUE in the mapFN function.

    0 讨论(0)
提交回复
热议问题