0
\$\begingroup\$

Is there a shorter way and does not involve nested for loops?

const checkIfSumFromTwoNumbers = (arrayOfNum, targetValue) => {
 let found = [];
 let result = [];
 for (let value of arrayOfNum) {
 if (found[targetValue - value] === true ) {
 result.push({[arrayOfNum.indexOf(value)]: value, [arrayOfNum.indexOf(targetValue-value)]: targetValue - value});
 }
 found[value] = true;
 }
 return result;
};
asked Nov 12, 2017 at 3:41
\$\endgroup\$
0

2 Answers 2

1
\$\begingroup\$

(削除) No, each number requires a second pass to determine whether combined with an existing one it is a match - doesn't mean it can't be short though e.g.

const checkIfSumFromTwoNumbers = (arrayOfNums, targetValue) => 
 arrayOfNums.reduce((matches, val) => {
 const target = arrayOfNums.find(x => (val + x) === targetValue);
 target && matches.push([val, target]);
 return matches;
 }, [])

(削除ここまで)

I was actually ignorant to the fact your code actually works which means it can be done in one pass :) here's a slightly neater / more concise version of what you already have:

const checkIfSumFromTwoNumbers = (arrayOfNum, targetValue) => {
 const seen = {};
 return arrayOfNum.reduce((matches, val) => {
 const delta = targetValue - val;
 seen[delta] && matches.push([delta, val]);
 seen[val] = true;
 return matches;
 }, []);
};
answered Nov 12, 2017 at 4:08
\$\endgroup\$
12
  • \$\begingroup\$ First time using code review and this was a great answer. Thank you so much for taking the time to write that out. \$\endgroup\$ Commented Nov 12, 2017 at 4:15
  • \$\begingroup\$ @ChaseNorton no worries, just realised that the current implementation would result in duplicates e.g. if your target value was 7 and you had an array of 1-5, 2+5 & 5+2 would match - presumably you wouldn't want this? \$\endgroup\$ Commented Nov 12, 2017 at 4:24
  • \$\begingroup\$ A single pass solution is possible \$\endgroup\$ Commented Nov 12, 2017 at 4:26
  • \$\begingroup\$ @wOxxOm actually, with a little tweak that solution would work. At the minute it just matches on the first sum - I may be able to adapt my own answer to be one pass now that I can see it has duplicates. \$\endgroup\$ Commented Nov 12, 2017 at 4:39
  • 1
    \$\begingroup\$ @ChaseNorton code would be more or less the same other than swapping out the seen object for a Set. When adding to the set use seen.add(x) and when checking seen.has(x). \$\endgroup\$ Commented Nov 12, 2017 at 20:36
0
\$\begingroup\$

Since you mentioned shorter, the same array can be used for found and result:

const f = (a, t) => a.reduce((r, v) => (r[v - t] && r.push([t - v, v]), r[-v] = 1, r), [])
const f2 = (a, t) => a.reduce((r, v, i) => 
 (r[v - t] + 1 && r.push({ [r[v - t]]: t - v, [i]: v }), r[-v] = i, r), [])
const a = [3, 1, 2, 2, 3, 4], l = console.log, j = JSON.stringify
l(j( f(a, 6) ))
l(j( f2(a, 6) ))
// .slice() can be added to the result to make a copy without the "hidden" items:
l(j({ ...f(a, 6) }))
l(j({ ...f(a, 6).slice() }))

Hacky code golfed answers like this are probably not very appropriate on Code Review, so hopefully it's not too much against the rules. A bit of explanation:

In JavaScript, Array is actually an object that uses positive integer properties. For Example:

a = []
a[1] = 1
a.b = 'c'
a[-1] = -1
a[0.1] = 0.1
a[/./g] = /./g
console.log(a) // [undefined, 1] - only the positive integer properties
console.log({...a}) // { "1": 1, "b": "c", "-1": -1, "0.1": 0.1, "/./g": /./g }

So this part r[-v] = 1 adds a key -v to the array, and r[v - t] && checks if the array has entry with key -(target - value), and if the entry's value evaluates to true.

Another part is the Comma Operator. In JavaScript result = (expresion1, expresion2) evaluates both expressions and returns the result of the last one.

answered Nov 12, 2017 at 21:43
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.