Construct an 2D array of contiguous elements comparing master and incident arrays











up vote
2
down vote

favorite












Requirement:



Based on mainArray which contains the master list of items, and compArray which has items of interest; construct a 2 dimensional third array that contains the array of contiguous elements.



The purpose of this requirement is for plotting poly-line on map wherever an incident occurred in contiguous manner, plotted using the finalArray of locations.



Example:



const mainArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
const compArray = [1, 2, 3, 6, 7, 11, 12, 13, 15];

// produces finalArray
[[ 1, 2, 3 ],[ 6, 7 ],[ 11, 12, 13 ],[ 15 ]]


My current solution:



console.clear();

const mainArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
const compArray = [1, 2, 3, 6, 7, 11, 12, 13, 15];
let compArrayIndex = 0;
let finalArray = ;
let currentArray = null;

for (let i = 0; i < mainArray.length; i++) {
const e = mainArray[i];

if (e === compArray[compArrayIndex]) {
if (!currentArray) {
currentArray = ;
}
currentArray.push(e);
compArrayIndex++;
} else {
if (currentArray) {
finalArray.push([...currentArray]);
currentArray = null;
}
}
}

if (currentArray) {
finalArray.push([...currentArray]);
currentArray = null;
}

console.log(mainArray);
console.log(compArray);
console.log('finl arr:');
for (let i = 0; i < finalArray.length; i++) {
const e = finalArray[i];
console.log(e);
}









share|improve this question







New contributor




Vijay is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
















  • 1




    Why does this question have close votes? The problem is explained, there's an example and the code is there and seems to be working.
    – IEatBagels
    16 hours ago















up vote
2
down vote

favorite












Requirement:



Based on mainArray which contains the master list of items, and compArray which has items of interest; construct a 2 dimensional third array that contains the array of contiguous elements.



The purpose of this requirement is for plotting poly-line on map wherever an incident occurred in contiguous manner, plotted using the finalArray of locations.



Example:



const mainArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
const compArray = [1, 2, 3, 6, 7, 11, 12, 13, 15];

// produces finalArray
[[ 1, 2, 3 ],[ 6, 7 ],[ 11, 12, 13 ],[ 15 ]]


My current solution:



console.clear();

const mainArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
const compArray = [1, 2, 3, 6, 7, 11, 12, 13, 15];
let compArrayIndex = 0;
let finalArray = ;
let currentArray = null;

for (let i = 0; i < mainArray.length; i++) {
const e = mainArray[i];

if (e === compArray[compArrayIndex]) {
if (!currentArray) {
currentArray = ;
}
currentArray.push(e);
compArrayIndex++;
} else {
if (currentArray) {
finalArray.push([...currentArray]);
currentArray = null;
}
}
}

if (currentArray) {
finalArray.push([...currentArray]);
currentArray = null;
}

console.log(mainArray);
console.log(compArray);
console.log('finl arr:');
for (let i = 0; i < finalArray.length; i++) {
const e = finalArray[i];
console.log(e);
}









share|improve this question







New contributor




Vijay is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
















  • 1




    Why does this question have close votes? The problem is explained, there's an example and the code is there and seems to be working.
    – IEatBagels
    16 hours ago













up vote
2
down vote

favorite









up vote
2
down vote

favorite











Requirement:



Based on mainArray which contains the master list of items, and compArray which has items of interest; construct a 2 dimensional third array that contains the array of contiguous elements.



The purpose of this requirement is for plotting poly-line on map wherever an incident occurred in contiguous manner, plotted using the finalArray of locations.



Example:



const mainArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
const compArray = [1, 2, 3, 6, 7, 11, 12, 13, 15];

// produces finalArray
[[ 1, 2, 3 ],[ 6, 7 ],[ 11, 12, 13 ],[ 15 ]]


My current solution:



console.clear();

const mainArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
const compArray = [1, 2, 3, 6, 7, 11, 12, 13, 15];
let compArrayIndex = 0;
let finalArray = ;
let currentArray = null;

for (let i = 0; i < mainArray.length; i++) {
const e = mainArray[i];

if (e === compArray[compArrayIndex]) {
if (!currentArray) {
currentArray = ;
}
currentArray.push(e);
compArrayIndex++;
} else {
if (currentArray) {
finalArray.push([...currentArray]);
currentArray = null;
}
}
}

if (currentArray) {
finalArray.push([...currentArray]);
currentArray = null;
}

console.log(mainArray);
console.log(compArray);
console.log('finl arr:');
for (let i = 0; i < finalArray.length; i++) {
const e = finalArray[i];
console.log(e);
}









share|improve this question







New contributor




Vijay is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











Requirement:



Based on mainArray which contains the master list of items, and compArray which has items of interest; construct a 2 dimensional third array that contains the array of contiguous elements.



The purpose of this requirement is for plotting poly-line on map wherever an incident occurred in contiguous manner, plotted using the finalArray of locations.



Example:



const mainArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
const compArray = [1, 2, 3, 6, 7, 11, 12, 13, 15];

// produces finalArray
[[ 1, 2, 3 ],[ 6, 7 ],[ 11, 12, 13 ],[ 15 ]]


My current solution:



console.clear();

const mainArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
const compArray = [1, 2, 3, 6, 7, 11, 12, 13, 15];
let compArrayIndex = 0;
let finalArray = ;
let currentArray = null;

for (let i = 0; i < mainArray.length; i++) {
const e = mainArray[i];

if (e === compArray[compArrayIndex]) {
if (!currentArray) {
currentArray = ;
}
currentArray.push(e);
compArrayIndex++;
} else {
if (currentArray) {
finalArray.push([...currentArray]);
currentArray = null;
}
}
}

if (currentArray) {
finalArray.push([...currentArray]);
currentArray = null;
}

console.log(mainArray);
console.log(compArray);
console.log('finl arr:');
for (let i = 0; i < finalArray.length; i++) {
const e = finalArray[i];
console.log(e);
}






javascript






share|improve this question







New contributor




Vijay is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|improve this question







New contributor




Vijay is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question






New contributor




Vijay is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked 2 days ago









Vijay

1164




1164




New contributor




Vijay is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





Vijay is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






Vijay is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.








  • 1




    Why does this question have close votes? The problem is explained, there's an example and the code is there and seems to be working.
    – IEatBagels
    16 hours ago














  • 1




    Why does this question have close votes? The problem is explained, there's an example and the code is there and seems to be working.
    – IEatBagels
    16 hours ago








1




1




Why does this question have close votes? The problem is explained, there's an example and the code is there and seems to be working.
– IEatBagels
16 hours ago




Why does this question have close votes? The problem is explained, there's an example and the code is there and seems to be working.
– IEatBagels
16 hours ago










2 Answers
2






active

oldest

votes

















up vote
1
down vote



accepted










Good algorithm



Your solution is good, however its implementation is somewhat poor.



Clear requirements



It is very unclear what inputs to expect so I must add...



The input arrays are sorted and contain unique values, I must assume a requirement that is true.



I deduce this from your code as if the above was not true your code would fail.



Style & code




  • The variable names are too long. Remember code is always in context and if you are handling arrays do you really need to add that in their names?

  • Don't copy the array, just push it to the result. finalArray.push([...currentArray]); can be finalArray.push(currentArray); The copy halves the performance of your code (see below)

  • Use undefined rather than null

  • Simplify the code by using else if when possible. You have } else { if (currentArray) { which can be } else if (currentArray) {


  • finalArray should be a constant.

  • Don't add code that is not needed. The last statement block up assign null to currentArray yet the variable is never used after that line.


Apart from the above points your algorithm is good as it has low complexity (if you use finalArray.push(currentArray) you halve the complexity as [...currentArray] requires iteration of each item).



You missed the opportunity to exit early. If you pass the end of the either arrays you know that no more items need to be added, however you continue to the end of the first array, which if longer than the second could mean many rundundent iterations.



If you change the for loop to...



for (let i = 0; i < mainArray.length && compArrayIndex < compArray.length; i++) {


...you gain a reduction in overall complexity.



Cleaning up your solution



Thus we can rewrite your algorithm as



function extractRuns(main, comp) { 
var seq, j = 0;
const result = ;
for (let i = 0; i < main.length && j < comp.length; i++) {
const e = main[i];
if (e === comp[j]) {
if (!seq) { seq = }
seq.push(e);
j++;
} else if (seq) {
result.push(seq);
seq = undefined;
}
}
if (seq) { result.push(seq) }
return result;
}


Short is not always best



I must point out that the existing answer by guest271314 is very poor as it has very bad complexity by using Array.includes and is forced to iterate each item in the main array as it has no way to exit early from Array.reduce.



Rewrite



I personally would have written the solution as below as it gains a little performance (not by reduced complexity) via an inner while loop. (I am a bit of an off grid performance freak :) )



function extractRuns(main, comp) { // both arrays must be sorted and contain unique values
var m = 0, c = 0, seq; // c and m are indexes
const result = , mLen = main.length, cLen = comp.length;
while (m < mLen && c < cLen) {
const a = main[m], b = comp[c];
if (a === b) {
c ++;
m ++;
result.push(seq = [a]);
while (m < mLen && r < cLen && main[m] === comp[c]) {
seq.push(main[m ++]);
c ++;
}
} else if (b < a) { c ++ }
else { m ++ }
}
return result;
}


But I think your solution is far more readable and only a few % points slower to not be an issue.






share|improve this answer



















  • 1




    I agree with the review, although the long variable names were just for making my current solutions intentions more clear in the question. Thank you for the review.
    – Vijay
    yesterday






  • 1




    @Vijay Re long names, Understandable but we must take the code at face value. It is assumed that the posted code is working production (release) code. On that I did forget to make a point that it should also have been as a function but again I understand that you wrote it as an example.
    – Blindman67
    yesterday






  • 1




    @Blindman67 "I must point out that the existing answer by guest271314 is very poor" Your answer should stand on its own without any reference to another users' answer. You should be able to remove that portion of text from your answer without affecting the remainder of your answer. At a minimum instead of referring to this user in you answer you could have simply suggested to use .find() instead of .includes() as that appears to be the only criticism of the answer that you are citing. Did not ask you to review this users' answer though since you insisted on doing so do so constructively
    – guest271314
    yesterday












  • This is a good answer but I realllyyy can't agree with "The variable names are too long"
    – IEatBagels
    16 hours ago










  • @IEatBagels How does mainArray improve on main its an array why add it to the name. compArrayIndex adds nothing to the readability of a 17 line function over j as a standard iteration index name. Long names make long lines that often means breaking lines apart that could be single line statements and expressions. Good names are short, don't include type, and are always read in context of the code they are declared in from which comes most of the semantic meaning. Long names are for long functions with many variables declared off page, and globals, both of which are bad.
    – Blindman67
    15 hours ago


















up vote
2
down vote













The code could be reduced to a single line by utilizing Array.prototype.reduce()






const mainArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
const compArray = [1, 2, 3, 6, 7, 11, 12, 13, 15];

const finalArray = mainArray.reduce((a, b) => {
// `c` is boolean result of checking if `compArray` includes `b`
// `x` is first, and if matching elements found, last array in `finalResult`
const [c, x] = [compArray.includes(b), a[a.length - 1]];
// if `c` push `b` to last array of `a`
if (c) x.push(b)
// else if `x.length` push a new array to `a`
else if (x.length) a.push();
// return `a`
return a;
}, []); // pass initial array containing single array `a` to `reduce`

console.log(finalArray);








share|improve this answer





















  • To filter empty arrays in the case of [1, 2, 3, 6, 7, 11, 12, 13] you can chain .filter(n=>n.length)
    – guest271314
    2 days ago










  • I must point out your answer is not really a review, that the solution you give is O(n^2) while the op's is O(n), and that the comments are too much.. I would have down voted if you were not a newbie but rather I upvote and encourage you to keep posting, keeping these points in mind of course. Really!!! .// return 'a' for return a; and // else if x.length` push a new array to a`` for else if (x.length) a.push();`
    – Blindman67
    yesterday










  • @Blindman67 Not sure what you mean? How did you determine O(n^2) and O(n)? Is your only criticism the use of .includes() instead of .find()? "down" vote is meaningless to this user.
    – guest271314
    yesterday










  • Array.includes or Array.find are both iterative searches, when done inside another iteration the worst case is O(n^2) with n the mean array size. Plus there is no way to exit early from Array.reduce if the other array is shorter.
    – Blindman67
    yesterday











Your Answer





StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");

StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});






Vijay is a new contributor. Be nice, and check out our Code of Conduct.










draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f208561%2fconstruct-an-2d-array-of-contiguous-elements-comparing-master-and-incident-array%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
1
down vote



accepted










Good algorithm



Your solution is good, however its implementation is somewhat poor.



Clear requirements



It is very unclear what inputs to expect so I must add...



The input arrays are sorted and contain unique values, I must assume a requirement that is true.



I deduce this from your code as if the above was not true your code would fail.



Style & code




  • The variable names are too long. Remember code is always in context and if you are handling arrays do you really need to add that in their names?

  • Don't copy the array, just push it to the result. finalArray.push([...currentArray]); can be finalArray.push(currentArray); The copy halves the performance of your code (see below)

  • Use undefined rather than null

  • Simplify the code by using else if when possible. You have } else { if (currentArray) { which can be } else if (currentArray) {


  • finalArray should be a constant.

  • Don't add code that is not needed. The last statement block up assign null to currentArray yet the variable is never used after that line.


Apart from the above points your algorithm is good as it has low complexity (if you use finalArray.push(currentArray) you halve the complexity as [...currentArray] requires iteration of each item).



You missed the opportunity to exit early. If you pass the end of the either arrays you know that no more items need to be added, however you continue to the end of the first array, which if longer than the second could mean many rundundent iterations.



If you change the for loop to...



for (let i = 0; i < mainArray.length && compArrayIndex < compArray.length; i++) {


...you gain a reduction in overall complexity.



Cleaning up your solution



Thus we can rewrite your algorithm as



function extractRuns(main, comp) { 
var seq, j = 0;
const result = ;
for (let i = 0; i < main.length && j < comp.length; i++) {
const e = main[i];
if (e === comp[j]) {
if (!seq) { seq = }
seq.push(e);
j++;
} else if (seq) {
result.push(seq);
seq = undefined;
}
}
if (seq) { result.push(seq) }
return result;
}


Short is not always best



I must point out that the existing answer by guest271314 is very poor as it has very bad complexity by using Array.includes and is forced to iterate each item in the main array as it has no way to exit early from Array.reduce.



Rewrite



I personally would have written the solution as below as it gains a little performance (not by reduced complexity) via an inner while loop. (I am a bit of an off grid performance freak :) )



function extractRuns(main, comp) { // both arrays must be sorted and contain unique values
var m = 0, c = 0, seq; // c and m are indexes
const result = , mLen = main.length, cLen = comp.length;
while (m < mLen && c < cLen) {
const a = main[m], b = comp[c];
if (a === b) {
c ++;
m ++;
result.push(seq = [a]);
while (m < mLen && r < cLen && main[m] === comp[c]) {
seq.push(main[m ++]);
c ++;
}
} else if (b < a) { c ++ }
else { m ++ }
}
return result;
}


But I think your solution is far more readable and only a few % points slower to not be an issue.






share|improve this answer



















  • 1




    I agree with the review, although the long variable names were just for making my current solutions intentions more clear in the question. Thank you for the review.
    – Vijay
    yesterday






  • 1




    @Vijay Re long names, Understandable but we must take the code at face value. It is assumed that the posted code is working production (release) code. On that I did forget to make a point that it should also have been as a function but again I understand that you wrote it as an example.
    – Blindman67
    yesterday






  • 1




    @Blindman67 "I must point out that the existing answer by guest271314 is very poor" Your answer should stand on its own without any reference to another users' answer. You should be able to remove that portion of text from your answer without affecting the remainder of your answer. At a minimum instead of referring to this user in you answer you could have simply suggested to use .find() instead of .includes() as that appears to be the only criticism of the answer that you are citing. Did not ask you to review this users' answer though since you insisted on doing so do so constructively
    – guest271314
    yesterday












  • This is a good answer but I realllyyy can't agree with "The variable names are too long"
    – IEatBagels
    16 hours ago










  • @IEatBagels How does mainArray improve on main its an array why add it to the name. compArrayIndex adds nothing to the readability of a 17 line function over j as a standard iteration index name. Long names make long lines that often means breaking lines apart that could be single line statements and expressions. Good names are short, don't include type, and are always read in context of the code they are declared in from which comes most of the semantic meaning. Long names are for long functions with many variables declared off page, and globals, both of which are bad.
    – Blindman67
    15 hours ago















up vote
1
down vote



accepted










Good algorithm



Your solution is good, however its implementation is somewhat poor.



Clear requirements



It is very unclear what inputs to expect so I must add...



The input arrays are sorted and contain unique values, I must assume a requirement that is true.



I deduce this from your code as if the above was not true your code would fail.



Style & code




  • The variable names are too long. Remember code is always in context and if you are handling arrays do you really need to add that in their names?

  • Don't copy the array, just push it to the result. finalArray.push([...currentArray]); can be finalArray.push(currentArray); The copy halves the performance of your code (see below)

  • Use undefined rather than null

  • Simplify the code by using else if when possible. You have } else { if (currentArray) { which can be } else if (currentArray) {


  • finalArray should be a constant.

  • Don't add code that is not needed. The last statement block up assign null to currentArray yet the variable is never used after that line.


Apart from the above points your algorithm is good as it has low complexity (if you use finalArray.push(currentArray) you halve the complexity as [...currentArray] requires iteration of each item).



You missed the opportunity to exit early. If you pass the end of the either arrays you know that no more items need to be added, however you continue to the end of the first array, which if longer than the second could mean many rundundent iterations.



If you change the for loop to...



for (let i = 0; i < mainArray.length && compArrayIndex < compArray.length; i++) {


...you gain a reduction in overall complexity.



Cleaning up your solution



Thus we can rewrite your algorithm as



function extractRuns(main, comp) { 
var seq, j = 0;
const result = ;
for (let i = 0; i < main.length && j < comp.length; i++) {
const e = main[i];
if (e === comp[j]) {
if (!seq) { seq = }
seq.push(e);
j++;
} else if (seq) {
result.push(seq);
seq = undefined;
}
}
if (seq) { result.push(seq) }
return result;
}


Short is not always best



I must point out that the existing answer by guest271314 is very poor as it has very bad complexity by using Array.includes and is forced to iterate each item in the main array as it has no way to exit early from Array.reduce.



Rewrite



I personally would have written the solution as below as it gains a little performance (not by reduced complexity) via an inner while loop. (I am a bit of an off grid performance freak :) )



function extractRuns(main, comp) { // both arrays must be sorted and contain unique values
var m = 0, c = 0, seq; // c and m are indexes
const result = , mLen = main.length, cLen = comp.length;
while (m < mLen && c < cLen) {
const a = main[m], b = comp[c];
if (a === b) {
c ++;
m ++;
result.push(seq = [a]);
while (m < mLen && r < cLen && main[m] === comp[c]) {
seq.push(main[m ++]);
c ++;
}
} else if (b < a) { c ++ }
else { m ++ }
}
return result;
}


But I think your solution is far more readable and only a few % points slower to not be an issue.






share|improve this answer



















  • 1




    I agree with the review, although the long variable names were just for making my current solutions intentions more clear in the question. Thank you for the review.
    – Vijay
    yesterday






  • 1




    @Vijay Re long names, Understandable but we must take the code at face value. It is assumed that the posted code is working production (release) code. On that I did forget to make a point that it should also have been as a function but again I understand that you wrote it as an example.
    – Blindman67
    yesterday






  • 1




    @Blindman67 "I must point out that the existing answer by guest271314 is very poor" Your answer should stand on its own without any reference to another users' answer. You should be able to remove that portion of text from your answer without affecting the remainder of your answer. At a minimum instead of referring to this user in you answer you could have simply suggested to use .find() instead of .includes() as that appears to be the only criticism of the answer that you are citing. Did not ask you to review this users' answer though since you insisted on doing so do so constructively
    – guest271314
    yesterday












  • This is a good answer but I realllyyy can't agree with "The variable names are too long"
    – IEatBagels
    16 hours ago










  • @IEatBagels How does mainArray improve on main its an array why add it to the name. compArrayIndex adds nothing to the readability of a 17 line function over j as a standard iteration index name. Long names make long lines that often means breaking lines apart that could be single line statements and expressions. Good names are short, don't include type, and are always read in context of the code they are declared in from which comes most of the semantic meaning. Long names are for long functions with many variables declared off page, and globals, both of which are bad.
    – Blindman67
    15 hours ago













up vote
1
down vote



accepted







up vote
1
down vote



accepted






Good algorithm



Your solution is good, however its implementation is somewhat poor.



Clear requirements



It is very unclear what inputs to expect so I must add...



The input arrays are sorted and contain unique values, I must assume a requirement that is true.



I deduce this from your code as if the above was not true your code would fail.



Style & code




  • The variable names are too long. Remember code is always in context and if you are handling arrays do you really need to add that in their names?

  • Don't copy the array, just push it to the result. finalArray.push([...currentArray]); can be finalArray.push(currentArray); The copy halves the performance of your code (see below)

  • Use undefined rather than null

  • Simplify the code by using else if when possible. You have } else { if (currentArray) { which can be } else if (currentArray) {


  • finalArray should be a constant.

  • Don't add code that is not needed. The last statement block up assign null to currentArray yet the variable is never used after that line.


Apart from the above points your algorithm is good as it has low complexity (if you use finalArray.push(currentArray) you halve the complexity as [...currentArray] requires iteration of each item).



You missed the opportunity to exit early. If you pass the end of the either arrays you know that no more items need to be added, however you continue to the end of the first array, which if longer than the second could mean many rundundent iterations.



If you change the for loop to...



for (let i = 0; i < mainArray.length && compArrayIndex < compArray.length; i++) {


...you gain a reduction in overall complexity.



Cleaning up your solution



Thus we can rewrite your algorithm as



function extractRuns(main, comp) { 
var seq, j = 0;
const result = ;
for (let i = 0; i < main.length && j < comp.length; i++) {
const e = main[i];
if (e === comp[j]) {
if (!seq) { seq = }
seq.push(e);
j++;
} else if (seq) {
result.push(seq);
seq = undefined;
}
}
if (seq) { result.push(seq) }
return result;
}


Short is not always best



I must point out that the existing answer by guest271314 is very poor as it has very bad complexity by using Array.includes and is forced to iterate each item in the main array as it has no way to exit early from Array.reduce.



Rewrite



I personally would have written the solution as below as it gains a little performance (not by reduced complexity) via an inner while loop. (I am a bit of an off grid performance freak :) )



function extractRuns(main, comp) { // both arrays must be sorted and contain unique values
var m = 0, c = 0, seq; // c and m are indexes
const result = , mLen = main.length, cLen = comp.length;
while (m < mLen && c < cLen) {
const a = main[m], b = comp[c];
if (a === b) {
c ++;
m ++;
result.push(seq = [a]);
while (m < mLen && r < cLen && main[m] === comp[c]) {
seq.push(main[m ++]);
c ++;
}
} else if (b < a) { c ++ }
else { m ++ }
}
return result;
}


But I think your solution is far more readable and only a few % points slower to not be an issue.






share|improve this answer














Good algorithm



Your solution is good, however its implementation is somewhat poor.



Clear requirements



It is very unclear what inputs to expect so I must add...



The input arrays are sorted and contain unique values, I must assume a requirement that is true.



I deduce this from your code as if the above was not true your code would fail.



Style & code




  • The variable names are too long. Remember code is always in context and if you are handling arrays do you really need to add that in their names?

  • Don't copy the array, just push it to the result. finalArray.push([...currentArray]); can be finalArray.push(currentArray); The copy halves the performance of your code (see below)

  • Use undefined rather than null

  • Simplify the code by using else if when possible. You have } else { if (currentArray) { which can be } else if (currentArray) {


  • finalArray should be a constant.

  • Don't add code that is not needed. The last statement block up assign null to currentArray yet the variable is never used after that line.


Apart from the above points your algorithm is good as it has low complexity (if you use finalArray.push(currentArray) you halve the complexity as [...currentArray] requires iteration of each item).



You missed the opportunity to exit early. If you pass the end of the either arrays you know that no more items need to be added, however you continue to the end of the first array, which if longer than the second could mean many rundundent iterations.



If you change the for loop to...



for (let i = 0; i < mainArray.length && compArrayIndex < compArray.length; i++) {


...you gain a reduction in overall complexity.



Cleaning up your solution



Thus we can rewrite your algorithm as



function extractRuns(main, comp) { 
var seq, j = 0;
const result = ;
for (let i = 0; i < main.length && j < comp.length; i++) {
const e = main[i];
if (e === comp[j]) {
if (!seq) { seq = }
seq.push(e);
j++;
} else if (seq) {
result.push(seq);
seq = undefined;
}
}
if (seq) { result.push(seq) }
return result;
}


Short is not always best



I must point out that the existing answer by guest271314 is very poor as it has very bad complexity by using Array.includes and is forced to iterate each item in the main array as it has no way to exit early from Array.reduce.



Rewrite



I personally would have written the solution as below as it gains a little performance (not by reduced complexity) via an inner while loop. (I am a bit of an off grid performance freak :) )



function extractRuns(main, comp) { // both arrays must be sorted and contain unique values
var m = 0, c = 0, seq; // c and m are indexes
const result = , mLen = main.length, cLen = comp.length;
while (m < mLen && c < cLen) {
const a = main[m], b = comp[c];
if (a === b) {
c ++;
m ++;
result.push(seq = [a]);
while (m < mLen && r < cLen && main[m] === comp[c]) {
seq.push(main[m ++]);
c ++;
}
} else if (b < a) { c ++ }
else { m ++ }
}
return result;
}


But I think your solution is far more readable and only a few % points slower to not be an issue.







share|improve this answer














share|improve this answer



share|improve this answer








edited yesterday

























answered yesterday









Blindman67

6,6241521




6,6241521








  • 1




    I agree with the review, although the long variable names were just for making my current solutions intentions more clear in the question. Thank you for the review.
    – Vijay
    yesterday






  • 1




    @Vijay Re long names, Understandable but we must take the code at face value. It is assumed that the posted code is working production (release) code. On that I did forget to make a point that it should also have been as a function but again I understand that you wrote it as an example.
    – Blindman67
    yesterday






  • 1




    @Blindman67 "I must point out that the existing answer by guest271314 is very poor" Your answer should stand on its own without any reference to another users' answer. You should be able to remove that portion of text from your answer without affecting the remainder of your answer. At a minimum instead of referring to this user in you answer you could have simply suggested to use .find() instead of .includes() as that appears to be the only criticism of the answer that you are citing. Did not ask you to review this users' answer though since you insisted on doing so do so constructively
    – guest271314
    yesterday












  • This is a good answer but I realllyyy can't agree with "The variable names are too long"
    – IEatBagels
    16 hours ago










  • @IEatBagels How does mainArray improve on main its an array why add it to the name. compArrayIndex adds nothing to the readability of a 17 line function over j as a standard iteration index name. Long names make long lines that often means breaking lines apart that could be single line statements and expressions. Good names are short, don't include type, and are always read in context of the code they are declared in from which comes most of the semantic meaning. Long names are for long functions with many variables declared off page, and globals, both of which are bad.
    – Blindman67
    15 hours ago














  • 1




    I agree with the review, although the long variable names were just for making my current solutions intentions more clear in the question. Thank you for the review.
    – Vijay
    yesterday






  • 1




    @Vijay Re long names, Understandable but we must take the code at face value. It is assumed that the posted code is working production (release) code. On that I did forget to make a point that it should also have been as a function but again I understand that you wrote it as an example.
    – Blindman67
    yesterday






  • 1




    @Blindman67 "I must point out that the existing answer by guest271314 is very poor" Your answer should stand on its own without any reference to another users' answer. You should be able to remove that portion of text from your answer without affecting the remainder of your answer. At a minimum instead of referring to this user in you answer you could have simply suggested to use .find() instead of .includes() as that appears to be the only criticism of the answer that you are citing. Did not ask you to review this users' answer though since you insisted on doing so do so constructively
    – guest271314
    yesterday












  • This is a good answer but I realllyyy can't agree with "The variable names are too long"
    – IEatBagels
    16 hours ago










  • @IEatBagels How does mainArray improve on main its an array why add it to the name. compArrayIndex adds nothing to the readability of a 17 line function over j as a standard iteration index name. Long names make long lines that often means breaking lines apart that could be single line statements and expressions. Good names are short, don't include type, and are always read in context of the code they are declared in from which comes most of the semantic meaning. Long names are for long functions with many variables declared off page, and globals, both of which are bad.
    – Blindman67
    15 hours ago








1




1




I agree with the review, although the long variable names were just for making my current solutions intentions more clear in the question. Thank you for the review.
– Vijay
yesterday




I agree with the review, although the long variable names were just for making my current solutions intentions more clear in the question. Thank you for the review.
– Vijay
yesterday




1




1




@Vijay Re long names, Understandable but we must take the code at face value. It is assumed that the posted code is working production (release) code. On that I did forget to make a point that it should also have been as a function but again I understand that you wrote it as an example.
– Blindman67
yesterday




@Vijay Re long names, Understandable but we must take the code at face value. It is assumed that the posted code is working production (release) code. On that I did forget to make a point that it should also have been as a function but again I understand that you wrote it as an example.
– Blindman67
yesterday




1




1




@Blindman67 "I must point out that the existing answer by guest271314 is very poor" Your answer should stand on its own without any reference to another users' answer. You should be able to remove that portion of text from your answer without affecting the remainder of your answer. At a minimum instead of referring to this user in you answer you could have simply suggested to use .find() instead of .includes() as that appears to be the only criticism of the answer that you are citing. Did not ask you to review this users' answer though since you insisted on doing so do so constructively
– guest271314
yesterday






@Blindman67 "I must point out that the existing answer by guest271314 is very poor" Your answer should stand on its own without any reference to another users' answer. You should be able to remove that portion of text from your answer without affecting the remainder of your answer. At a minimum instead of referring to this user in you answer you could have simply suggested to use .find() instead of .includes() as that appears to be the only criticism of the answer that you are citing. Did not ask you to review this users' answer though since you insisted on doing so do so constructively
– guest271314
yesterday














This is a good answer but I realllyyy can't agree with "The variable names are too long"
– IEatBagels
16 hours ago




This is a good answer but I realllyyy can't agree with "The variable names are too long"
– IEatBagels
16 hours ago












@IEatBagels How does mainArray improve on main its an array why add it to the name. compArrayIndex adds nothing to the readability of a 17 line function over j as a standard iteration index name. Long names make long lines that often means breaking lines apart that could be single line statements and expressions. Good names are short, don't include type, and are always read in context of the code they are declared in from which comes most of the semantic meaning. Long names are for long functions with many variables declared off page, and globals, both of which are bad.
– Blindman67
15 hours ago




@IEatBagels How does mainArray improve on main its an array why add it to the name. compArrayIndex adds nothing to the readability of a 17 line function over j as a standard iteration index name. Long names make long lines that often means breaking lines apart that could be single line statements and expressions. Good names are short, don't include type, and are always read in context of the code they are declared in from which comes most of the semantic meaning. Long names are for long functions with many variables declared off page, and globals, both of which are bad.
– Blindman67
15 hours ago












up vote
2
down vote













The code could be reduced to a single line by utilizing Array.prototype.reduce()






const mainArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
const compArray = [1, 2, 3, 6, 7, 11, 12, 13, 15];

const finalArray = mainArray.reduce((a, b) => {
// `c` is boolean result of checking if `compArray` includes `b`
// `x` is first, and if matching elements found, last array in `finalResult`
const [c, x] = [compArray.includes(b), a[a.length - 1]];
// if `c` push `b` to last array of `a`
if (c) x.push(b)
// else if `x.length` push a new array to `a`
else if (x.length) a.push();
// return `a`
return a;
}, []); // pass initial array containing single array `a` to `reduce`

console.log(finalArray);








share|improve this answer





















  • To filter empty arrays in the case of [1, 2, 3, 6, 7, 11, 12, 13] you can chain .filter(n=>n.length)
    – guest271314
    2 days ago










  • I must point out your answer is not really a review, that the solution you give is O(n^2) while the op's is O(n), and that the comments are too much.. I would have down voted if you were not a newbie but rather I upvote and encourage you to keep posting, keeping these points in mind of course. Really!!! .// return 'a' for return a; and // else if x.length` push a new array to a`` for else if (x.length) a.push();`
    – Blindman67
    yesterday










  • @Blindman67 Not sure what you mean? How did you determine O(n^2) and O(n)? Is your only criticism the use of .includes() instead of .find()? "down" vote is meaningless to this user.
    – guest271314
    yesterday










  • Array.includes or Array.find are both iterative searches, when done inside another iteration the worst case is O(n^2) with n the mean array size. Plus there is no way to exit early from Array.reduce if the other array is shorter.
    – Blindman67
    yesterday















up vote
2
down vote













The code could be reduced to a single line by utilizing Array.prototype.reduce()






const mainArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
const compArray = [1, 2, 3, 6, 7, 11, 12, 13, 15];

const finalArray = mainArray.reduce((a, b) => {
// `c` is boolean result of checking if `compArray` includes `b`
// `x` is first, and if matching elements found, last array in `finalResult`
const [c, x] = [compArray.includes(b), a[a.length - 1]];
// if `c` push `b` to last array of `a`
if (c) x.push(b)
// else if `x.length` push a new array to `a`
else if (x.length) a.push();
// return `a`
return a;
}, []); // pass initial array containing single array `a` to `reduce`

console.log(finalArray);








share|improve this answer





















  • To filter empty arrays in the case of [1, 2, 3, 6, 7, 11, 12, 13] you can chain .filter(n=>n.length)
    – guest271314
    2 days ago










  • I must point out your answer is not really a review, that the solution you give is O(n^2) while the op's is O(n), and that the comments are too much.. I would have down voted if you were not a newbie but rather I upvote and encourage you to keep posting, keeping these points in mind of course. Really!!! .// return 'a' for return a; and // else if x.length` push a new array to a`` for else if (x.length) a.push();`
    – Blindman67
    yesterday










  • @Blindman67 Not sure what you mean? How did you determine O(n^2) and O(n)? Is your only criticism the use of .includes() instead of .find()? "down" vote is meaningless to this user.
    – guest271314
    yesterday










  • Array.includes or Array.find are both iterative searches, when done inside another iteration the worst case is O(n^2) with n the mean array size. Plus there is no way to exit early from Array.reduce if the other array is shorter.
    – Blindman67
    yesterday













up vote
2
down vote










up vote
2
down vote









The code could be reduced to a single line by utilizing Array.prototype.reduce()






const mainArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
const compArray = [1, 2, 3, 6, 7, 11, 12, 13, 15];

const finalArray = mainArray.reduce((a, b) => {
// `c` is boolean result of checking if `compArray` includes `b`
// `x` is first, and if matching elements found, last array in `finalResult`
const [c, x] = [compArray.includes(b), a[a.length - 1]];
// if `c` push `b` to last array of `a`
if (c) x.push(b)
// else if `x.length` push a new array to `a`
else if (x.length) a.push();
// return `a`
return a;
}, []); // pass initial array containing single array `a` to `reduce`

console.log(finalArray);








share|improve this answer












The code could be reduced to a single line by utilizing Array.prototype.reduce()






const mainArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
const compArray = [1, 2, 3, 6, 7, 11, 12, 13, 15];

const finalArray = mainArray.reduce((a, b) => {
// `c` is boolean result of checking if `compArray` includes `b`
// `x` is first, and if matching elements found, last array in `finalResult`
const [c, x] = [compArray.includes(b), a[a.length - 1]];
// if `c` push `b` to last array of `a`
if (c) x.push(b)
// else if `x.length` push a new array to `a`
else if (x.length) a.push();
// return `a`
return a;
}, []); // pass initial array containing single array `a` to `reduce`

console.log(finalArray);








const mainArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
const compArray = [1, 2, 3, 6, 7, 11, 12, 13, 15];

const finalArray = mainArray.reduce((a, b) => {
// `c` is boolean result of checking if `compArray` includes `b`
// `x` is first, and if matching elements found, last array in `finalResult`
const [c, x] = [compArray.includes(b), a[a.length - 1]];
// if `c` push `b` to last array of `a`
if (c) x.push(b)
// else if `x.length` push a new array to `a`
else if (x.length) a.push();
// return `a`
return a;
}, []); // pass initial array containing single array `a` to `reduce`

console.log(finalArray);





const mainArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
const compArray = [1, 2, 3, 6, 7, 11, 12, 13, 15];

const finalArray = mainArray.reduce((a, b) => {
// `c` is boolean result of checking if `compArray` includes `b`
// `x` is first, and if matching elements found, last array in `finalResult`
const [c, x] = [compArray.includes(b), a[a.length - 1]];
// if `c` push `b` to last array of `a`
if (c) x.push(b)
// else if `x.length` push a new array to `a`
else if (x.length) a.push();
// return `a`
return a;
}, []); // pass initial array containing single array `a` to `reduce`

console.log(finalArray);






share|improve this answer












share|improve this answer



share|improve this answer










answered 2 days ago









guest271314

1615




1615












  • To filter empty arrays in the case of [1, 2, 3, 6, 7, 11, 12, 13] you can chain .filter(n=>n.length)
    – guest271314
    2 days ago










  • I must point out your answer is not really a review, that the solution you give is O(n^2) while the op's is O(n), and that the comments are too much.. I would have down voted if you were not a newbie but rather I upvote and encourage you to keep posting, keeping these points in mind of course. Really!!! .// return 'a' for return a; and // else if x.length` push a new array to a`` for else if (x.length) a.push();`
    – Blindman67
    yesterday










  • @Blindman67 Not sure what you mean? How did you determine O(n^2) and O(n)? Is your only criticism the use of .includes() instead of .find()? "down" vote is meaningless to this user.
    – guest271314
    yesterday










  • Array.includes or Array.find are both iterative searches, when done inside another iteration the worst case is O(n^2) with n the mean array size. Plus there is no way to exit early from Array.reduce if the other array is shorter.
    – Blindman67
    yesterday


















  • To filter empty arrays in the case of [1, 2, 3, 6, 7, 11, 12, 13] you can chain .filter(n=>n.length)
    – guest271314
    2 days ago










  • I must point out your answer is not really a review, that the solution you give is O(n^2) while the op's is O(n), and that the comments are too much.. I would have down voted if you were not a newbie but rather I upvote and encourage you to keep posting, keeping these points in mind of course. Really!!! .// return 'a' for return a; and // else if x.length` push a new array to a`` for else if (x.length) a.push();`
    – Blindman67
    yesterday










  • @Blindman67 Not sure what you mean? How did you determine O(n^2) and O(n)? Is your only criticism the use of .includes() instead of .find()? "down" vote is meaningless to this user.
    – guest271314
    yesterday










  • Array.includes or Array.find are both iterative searches, when done inside another iteration the worst case is O(n^2) with n the mean array size. Plus there is no way to exit early from Array.reduce if the other array is shorter.
    – Blindman67
    yesterday
















To filter empty arrays in the case of [1, 2, 3, 6, 7, 11, 12, 13] you can chain .filter(n=>n.length)
– guest271314
2 days ago




To filter empty arrays in the case of [1, 2, 3, 6, 7, 11, 12, 13] you can chain .filter(n=>n.length)
– guest271314
2 days ago












I must point out your answer is not really a review, that the solution you give is O(n^2) while the op's is O(n), and that the comments are too much.. I would have down voted if you were not a newbie but rather I upvote and encourage you to keep posting, keeping these points in mind of course. Really!!! .// return 'a' for return a; and // else if x.length` push a new array to a`` for else if (x.length) a.push();`
– Blindman67
yesterday




I must point out your answer is not really a review, that the solution you give is O(n^2) while the op's is O(n), and that the comments are too much.. I would have down voted if you were not a newbie but rather I upvote and encourage you to keep posting, keeping these points in mind of course. Really!!! .// return 'a' for return a; and // else if x.length` push a new array to a`` for else if (x.length) a.push();`
– Blindman67
yesterday












@Blindman67 Not sure what you mean? How did you determine O(n^2) and O(n)? Is your only criticism the use of .includes() instead of .find()? "down" vote is meaningless to this user.
– guest271314
yesterday




@Blindman67 Not sure what you mean? How did you determine O(n^2) and O(n)? Is your only criticism the use of .includes() instead of .find()? "down" vote is meaningless to this user.
– guest271314
yesterday












Array.includes or Array.find are both iterative searches, when done inside another iteration the worst case is O(n^2) with n the mean array size. Plus there is no way to exit early from Array.reduce if the other array is shorter.
– Blindman67
yesterday




Array.includes or Array.find are both iterative searches, when done inside another iteration the worst case is O(n^2) with n the mean array size. Plus there is no way to exit early from Array.reduce if the other array is shorter.
– Blindman67
yesterday










Vijay is a new contributor. Be nice, and check out our Code of Conduct.










draft saved

draft discarded


















Vijay is a new contributor. Be nice, and check out our Code of Conduct.













Vijay is a new contributor. Be nice, and check out our Code of Conduct.












Vijay is a new contributor. Be nice, and check out our Code of Conduct.
















Thanks for contributing an answer to Code Review Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


Use MathJax to format equations. MathJax reference.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f208561%2fconstruct-an-2d-array-of-contiguous-elements-comparing-master-and-incident-array%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Morgemoulin

Scott Moir

Souastre