OiO.lk Community platform!

Oio.lk is an excellent forum for developers, providing a wide range of resources, discussions, and support for those in the developer community. Join oio.lk today to connect with like-minded professionals, share insights, and stay updated on the latest trends and technologies in the development field.
  You need to log in or register to access the solved answers to this problem.
  • You have reached the maximum number of guest views allowed
  • Please register below to remove this limitation

How do I conditionally deep merge objects in JavaScript with multiple keys

  • Thread starter Thread starter micahlt
  • Start date Start date
M

micahlt

Guest
The project I am working on is a trilingual dictionary. I have a database of words, and each word contains (among other things) an array of spelling variations and an array of objects representing definitions in all three languages, as seen below:


Code:
// Word object
{
  variants: ["chuyuchik", "chuyuchiikk"],
  definitions: [
    {
      en: {
        translation: "English definition",
        example: "English example",
      },
      es: {
        translation: "Spanish definition",
        example: "Spanish example",
      },
      tz: {
        example: "Tz'utujil example",
      },
    },
}

I'm trying to implement a feature where new words can be added to the database but if a word is a duplicate (based on what the variants array contains) they are merged. My problem occurs when trying to merge the definitions arrays in the two words. The flow I'm trying to achieve is as follows:

  • Properties that are already in the original word take precedence and should not ever be overwritten.
  • If a translation in the new word is a duplicate of an existing translation in the original word (in the same language), but the new word has an example attached to it then that example should be put into the merged word in its respective place.
  • If there is a completely new translation, that translation and its example (if it exists) should be appended to the definitions array.
  • There should never be duplicate values in any field of the same language throughout the word (e.g., the first object's English example should never be the same as the second object's English example). In the case of duplicate values, the value that is from the old word should be preserved and the other value should become an empty string.

I've tried a bunch of different ways to achieve this - maps, loops, flattening out the objects - I can't seem to wrap my mind around it. Any suggestions?

Here's an example of what the before and after should be:


Code:
// Original definitions in word
const oldDefs = [{
  en: {
    translation: "EN 1",
    example: "ENGLISH EX 1",
  },
  es: {
    translation: "ES 1",
    example: "SPANISH EX 1",
  },
  tz: {
    example: "TZ EXAMPLE 1",
  },
}, {
  en: {
    translation: "EN 2",
    example: "",
  },
  es: {
    translation: "",
    example: "",
  },
  tz: {
    example: "",
  },
}]

// The definitions to merge into the original
const newDefs = [{
  en: {
    translation: "EN 2",
    example: "ENGLISH EX 2",
  },
  es: {
    translation: "ES 2",
    example: "SPANISH EX 2",
  },
  tz: {
    example: "TZ EXAMPLE 1",
  },
}]

// What the output should be
const output = [{
  en: {
    translation: "EN 1",
    example: "ENGLISH EX 1",
  },
  es: {
    translation: "ES 1",
    example: "SPANISH EX 1",
  },
  tz: {
    example: "TZ EXAMPLE 1",
  },
}, {
  en: {
    translation: "EN 2",
    example: "ENGLISH EX 2",
  },
  es: {
    translation: "ES 2",
    example: "SPANISH EX 2",
  },
  tz: {
    example: "",
  },
}]

<p>The project I am working on is a trilingual dictionary. I have a database of words, and each word contains (among other things) an array of spelling variations and an array of objects representing definitions in all three languages, as seen below:</p>
<p><div class="snippet" data-lang="js" data-hide="true" data-console="true" data-babel="false">
<div class="snippet-code snippet-currently-hidden">
<pre class="snippet-code-js lang-js prettyprint-override"><code>// Word object
{
variants: ["chuyuchik", "chuyuchiikk"],
definitions: [
{
en: {
translation: "English definition",
example: "English example",
},
es: {
translation: "Spanish definition",
example: "Spanish example",
},
tz: {
example: "Tz'utujil example",
},
},
}</code></pre>
</div>
</div>
</p>
<p>I'm trying to implement a feature where new words can be added to the database but if a word is a duplicate (based on what the <code>variants</code> array contains) they are merged. My problem occurs when trying to merge the <code>definitions</code> arrays in the two words. The flow I'm trying to achieve is as follows:</p>
<ul>
<li>Properties that are already in the original word take precedence and <strong>should not ever</strong> be overwritten.</li>
<li>If a <code>translation</code> in the new word is a duplicate of an existing <code>translation</code> in the original word (in the same language), but the new word has an example attached to it then that example should be put into the merged word in its respective place.</li>
<li>If there is a completely new <code>translation</code>, that <code>translation</code> and its <code>example</code> (if it exists) should be appended to the definitions array.</li>
<li>There should never be duplicate values in any field of the same language throughout the word (e.g., the first object's English example should never be the same as the second object's English example). In the case of duplicate values, the value that is from the old word should be preserved and the other value should become an empty string.</li>
</ul>
<p>I've tried a bunch of different ways to achieve this - maps, loops, flattening out the objects - I can't seem to wrap my mind around it. Any suggestions?</p>
<p>Here's an example of what the before and after should be:</p>
<p><div class="snippet" data-lang="js" data-hide="true" data-console="true" data-babel="false">
<div class="snippet-code snippet-currently-hidden">
<pre class="snippet-code-js lang-js prettyprint-override"><code>// Original definitions in word
const oldDefs = [{
en: {
translation: "EN 1",
example: "ENGLISH EX 1",
},
es: {
translation: "ES 1",
example: "SPANISH EX 1",
},
tz: {
example: "TZ EXAMPLE 1",
},
}, {
en: {
translation: "EN 2",
example: "",
},
es: {
translation: "",
example: "",
},
tz: {
example: "",
},
}]

// The definitions to merge into the original
const newDefs = [{
en: {
translation: "EN 2",
example: "ENGLISH EX 2",
},
es: {
translation: "ES 2",
example: "SPANISH EX 2",
},
tz: {
example: "TZ EXAMPLE 1",
},
}]

// What the output should be
const output = [{
en: {
translation: "EN 1",
example: "ENGLISH EX 1",
},
es: {
translation: "ES 1",
example: "SPANISH EX 1",
},
tz: {
example: "TZ EXAMPLE 1",
},
}, {
en: {
translation: "EN 2",
example: "ENGLISH EX 2",
},
es: {
translation: "ES 2",
example: "SPANISH EX 2",
},
tz: {
example: "",
},
}]</code></pre>
</div>
</div>
</p>
 

Latest posts

Online statistics

Members online
1
Guests online
5
Total visitors
6
Top