8
\$\begingroup\$

Challenge:

Resolve git conflict by resolveGitConflict(linesArray, resolveMode), where

linesArray is an array of strings

Example:

[
    "context1", 
    "context2", 
    "<<<<<<<", 
    "my changes1", 
    "=======", 
    "their changes1",
    ">>>>>>>",
    "context3",
    "context4",
    "<<<<<<<", 
    "my changes2", 
    "=======", 
    "their changes2",
    ">>>>>>>",
    "context5",
    "context6"
]   

resolveMode - a string indicate:

  • m: Keep only current branch's changes
  • t: Keep only other branch's changes
  • tm: Keep both changes, but put other branch's changes before current branch's changes
  • mt - Keep both changes, but put other branch's changes after current branch's changes
  • none - Keep no changes

Review

We have three solutions for that challenge. Please compare all of them and tell which one is better.

Solution 1

const resolveGitConflict = (linesArray, resolveMode, t = []) =>
  linesArray.reduce((p, c) => p.concat(
    t.length ?
      c === '>>>>>>>' ?
        (c = [].concat(resolveMode[0] ? t.splice(+(resolveMode[0] === 't'), 1)[0].concat(resolveMode[1] ? t[0] : []) : [])) &&
        (t = []) && c
      : c === '=======' ? t[1] = [] : t[+!!t[1]].push(c) && []
    : c === '<<<<<<<' ? t[0] = [] : [c]
  ), [])

Solution 2

function resolveGitConflict(linesArray, mode) {
    var [changes, curMode] = [{m: [], t: []}, ''];
    return linesArray.map(line => {
        var newLines = [];
        if (line === '<<<<<<<' || line === '=======')
            curMode = line === '<<<<<<<'? 'm' : 't';
        else if (line === '>>>>>>>') { 
            newLines = Array.from(mode).map(c => changes[c] || []).flat(1);
            [changes.m, changes.t, curMode] = [[], [], ''];
        } else
            (changes[curMode] || newLines).push(line);
        return newLines;
    }).flat(1);
}

Solution 3

function resolveGitConflict(lines, mode) {
  return lines.reduce((p, c) => {
    let last = p[p.length-1]
    if(typeof last === 'object' ) {
      if(c === '>>>>>>>') last = [].concat(last[mode[0]] || [], last[mode[1]] || [])
      else if(c === '=======') last.t = [] 
      else last[last.t ? 't' : 'm'].push(c)
      return p.slice(0, -1).concat(last)
    } else if(c === '<<<<<<<') c = {m: []}        
    return p.concat(c)
  }, [])
}
\$\endgroup\$
1
  • \$\begingroup\$ "tell which one is better" - what does "better" mean? performance? code readability? ... ? \$\endgroup\$ Commented Aug 19, 2020 at 9:19

1 Answer 1

1
\$\begingroup\$

It is difficult to tell "which one is better". As Jan mentioned in a comment:

"tell which one is better" - what does "better" mean? performance? code readability? ... ?

The notion of better is subjective.

I am drawn to the first solution as it uses the fewest lines, though readability suffers because the lines are quite long and there are nested ternary operators.

I notice Solution 2 uses ES6 features like arrow functions (as all solutions do) yet it uses the var keyword. Some believe there is no use for var in modern JS. The variable newLines could be declared with const if instead of re-assigning it in the else if block the length property was set to 0 to truncate it and the mapped values were spread into a call to the push method. Using const instead of let helps avoid accidental re-assignment and other bugs.

\$\endgroup\$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.