1

I have two arrays sorted and ready like this:

const mains = [1, 5, 6, 8 , 12];
const secondaries = [1, 6, 12];

I want to create a div with multiple spans dynamically based on above arrays like theses:

<span class="main">${unit}</span>

<span class="secondary">${unit}</span>

The issue is I'm unable to find a proper solution to sort both arrays and create those spans .

In the given arrays the result should be this:

<span class="main"> 1 </span>

<span class="secondary"> 1 </span>

<span class="main"> 5 </span>

<span class="main"> 6 </span>

<span class="secondary"> 6 </span>

<span class="main"> 8 </span>

<span class="main"> 12 </span>

<span class="secondary"> 12 </span>
3
  • @AlanOmar Won't that lose the "main" vs. "secondary" distinction? Commented Nov 11, 2021 at 17:43
  • 1
    may you give a little more context ? Commented Nov 11, 2021 at 17:48
  • Can there be elements in secondaries that aren't in mains? Where should they be in the output? Commented Nov 11, 2021 at 17:52

5 Answers 5

1

If you transform your items into objects that remember which collection they came from, then you can merge them into a single array and sort them / process them uniformly.

const mains = [1, 5, 6, 8 , 12];
const secondaries = [1, 6, 12];
const objectify = (array, key) => array.map(value => ({ key, value }));
const temp = [...objectify(mains, 'main'), ...objectify(secondaries, 'secondary')];
temp.sort((a, b) => a.value - b.value);
const result = temp.map(({key, value}) => `<span class="${key}"> ${value} </span>`).join('\n');
console.log(result);

value of temp:

[
  { key: 'main', value: 1 },
  { key: 'main', value: 5 },
  { key: 'main', value: 6 },
  { key: 'main', value: 8 },
  { key: 'main', value: 12 },
  { key: 'secondary', value: 1 },
  { key: 'secondary', value: 6 },
  { key: 'secondary', value: 12 }
]

This temp array should be straightforward to sort by value and map to what you want.

Sign up to request clarification or add additional context in comments.

Comments

1

Loop over the mains array, and check if there's a corresponding element in secondaries:

html = '';
mains.foreach(main => {
    html += `<span class="main"> {$main} </span>`;
    if (secondaries.includes(main) {
        html += `<span class="secondary"> {$main} </span>`;
    }
});

If the arrays are large, you should convert secondaries to a Set and use secondaries.has(main) instead of secondaries.includes(main).

6 Comments

And what if there is no element in mains??
What is the expected output then?
I think this solution doesn't account for cases where elements are found in secondaries but not in mains.
I assumed from the question that the secondary should always go after the main with the same value. If there's nothing in mains then there are no matching values to go after.
@ChongLipPhang I assumed from the question that this isn't possible, or that the extra elements in secondaries shouldn't be shown.
|
1

You could merge them together, and as you merge them, create the span:

function span(val, class){
    console.log(`<span class=${class}>${val}</span>`);
function mergeAndSpan(main, secondary){
    let i = 0, j = 0;
    while(i < main.length && j < secondary.length){
        if(main[i] < secondary[j]){
            span(main[i], 'main')
            i++;
        } else {
            span(secondary[j], 'secondary')
            j++;
        }
    }
    while(i < main.length){
        span(main[i], 'main')
        i++;
    }
    while(j < secondary.length){
        span(secondary[j], 'secondary')
        j++;
    }
}
mergeAndSpan(mains, secondaries);

This is effectively the merge portion of mergesort, modified slightly to create spans instead of putting the elements into an array. What it does is iterates through both, creating a span for the lower element, and incrementing its' variable. Then, once one of the arrays is empty, then it iterates through the other array and creates the span for each of its' elements.

And, because it is performing an operation on all of n elements, it takes O(n) time.

Comments

1

const mains = [1, 5, 6, 8 , 12];
const secondaries = [1, 6, 12];

const min = Math.min(...mains, ...secondaries);
const max = Math.max(...mains, ...secondaries); 

for (let i=min; i<=max; i++){
  if (mains.includes(i)) console.log(`<span class="main">${i}</span>`);
  if (secondaries.includes(i)) console.log(`<span class="secondaries">${i}</span>`);
}

5 Comments

How is (max - min) lookups using .includes O(n)? Looks like O(n^2) to me. (.includes is specified as a linear search) Even if includes were implemented as a hash table, it's likely at best n log n, Possibly approaching O(n) with infinitely large hash space.
@Wyck Yes. My mistake!
@Chong Lip Phang what did you change?
Anyway, my solution is more suited towards smaller arrays. Though simple, it is by no means the most efficient algorithm.
Using this solution, you won't need to sort the two arrays first!
0

Another approach ...

'use strict';

function merge(a, b) {
    const
        genA = a[Symbol.iterator](),
        genB = b[Symbol.iterator]();

    let endA = false,
        endB = false,
        takeA = true,
        takeB = true,
        valueA,
        valueB;

    while (true) {
        if (!endA && takeA) ({ done: endA, value: valueA } = genA.next());
        if (!endB && takeB) ({ done: endB, value: valueB } = genB.next());

        if (endA && endB) break;

        takeA = !endA;
        takeB = !endB;

        if (takeA && takeB) {
            if (valueA < valueB) takeB = false;
            if (valueA > valueB) takeA = false;
        }

        if (takeA) console.log(`<span class="main">${valueA}</span>`);
        if (takeB) console.log(`<span class="secondaries">${valueB}</span>`);
    }
}

const
    mains = [1, 5, 6, 8, 12],
    secondaries = [1, 6, 12];

merge(mains, secondaries);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Comments

Your Answer

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.