0

I have this data:

const fetchedServices = [
  {
    _id: "5ee71bbfa7e903bfe2b324b2",
    en: {
      title: 'Leasing Equipment EN',
      description: 'We offer short and long term leases of both new and existing containers. New container equipment ex. works or positioned to your place of demand and existing containers from our depots.'
    },
    nl: {
      title: 'Leasing Equipment NL',
      description: 'We offer short and long term leases of both new and existing containers. New container equipment ex. works or positioned to your place of demand and existing containers from our depots.'
    },
  },
  {
    _id: "5ee73429a7e903bfe2b324b3",
    en: {
      title: 'Lease Purchase EN',
      description: 'The Lease Purchase Option we offer usually fulfills the requirements of the shipping lines, forwarders, terminals and other companies in the Transport industry, for their long term investment in containers and related equipment.'
    },
    nl: {
      title: 'Lease Purchase NL',
      description: 'The Lease Purchase Option we offer usually fulfills the requirements of the shipping lines, forwarders, terminals and other companies in the Transport industry, for their long term investment in containers and related equipment.'
    },
  }
];

And I parse it with this function:

const filterDataByLanguage = (data, addLang, removeLang) => {
    const arr = data.slice(0);
    let results = [];

    for (let i = 0; i < arr.length; i++) {
        delete arr[i][removeLang];
        results.push(arr[i]);
        for (key in arr[i][addLang]) {
            results[i][key] = arr[i][addLang][key]
        }
        delete arr[i][addLang];
    }
    return results;
}

I use this function to get data for to specific files, en.json and nl.json, like that:

let enData = filterDataByLanguage(fetchedServices, 'en', 'nl');
let nlData = filterDataByLanguage(fetchedServices, 'nl', 'en');

The problem is the first call is modify input array (data).

So my question is, how I can make input to return new instance when new function call is happening.

Thanks for any information.

Carnaru Valentin
  • 1,690
  • 17
  • 27

2 Answers2

3

As a general rule, I'd recommend very rarely mutating data (only mutate in cases where you're generating the data). You could take the lazy route and do a deep clone with something like lodash, but you could instead modify the function so it doesn't mutate the inputs:

const filterDataByLanguage = (data, addLang, removeLang) => {
    return data.map(item => {
       const { [removeLang]: removed, ...remaining } = item;
       return Object.assign(remaining, item[addLang]);
    });
}
Jacob
  • 77,566
  • 24
  • 149
  • 228
  • Will {...remaining} create a copy of an object with two levels, as in the OP's example? I think you need a deepcopy to ensure immutability – OlgaPp Jun 19 '20 at 18:55
  • I will try to use this approach to return a map and inside this to construct my new model, thank you! – Carnaru Valentin Jun 19 '20 at 18:58
  • @OlgaPp: it doesn't; `remaining` is a shallow copy. Whether you need to do a deep copy depends on if the consuming code plans to mutate or not. If you never mutate your data throughout your code base, there's no need for CPU-expensive cloning. – Jacob Jun 19 '20 at 19:00
0

Two suggestions.

  1. Why are you even deleting elements from arr[i] if you are not returning arr, and based on your comment you don't want your arr to be modified.

  2. var copy_obj = deepcopy(arr[i]) //deepcopy using any preferred method from https://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-deep-clone-an-object-in-javascript
    
    results.push(copy_obj);
    
    for (key in arr[i][addLang]) {
    
        results[i][key] = arr[i][addLang][key]
    
    }
    

What is the most efficient way to deep clone an object in JavaScript?

OlgaPp
  • 180
  • 11
  • The result is used in two different files, en and nl and the structure must be the same, ex: nl.json -> "title: "Title NL", en.json -> "title": "Title EN" – Carnaru Valentin Jun 19 '20 at 18:56