0

I have an input element and when the user types on it my code searches through an array for the input value and prints its element if it exists and it works fine. The problem is when I'm printing it I want to sort the final array alphabetically but also I want the searched strings index value position matches to come up first, alphabetically, then the rest after them. To explain this better say my array is ['testB', 'testD', 'testC', 'dtest', 'cTest'] and the user searched for test I want the final response array to be ["testB","testC","testD", "cTest", "dtest"] is kind of sorted but it gives priority to same index positioned characters. How can I achieve this?

const myArray = ['testB', 'testD', 'testC', 'dtest', 'cTest']
let tempArray = []

$('input').on('input', function() {
  tempArray = []
  for (var i = 0; i < myArray.length; i++) {
    if (myArray[i].toLowerCase().includes($(this).val().toLowerCase())) {
      tempArray.push(myArray[i])
    }
  }
  //I want it to write ["testB","testC","testD", "cTest", "dtest"]
  $('p').html(JSON.stringify(tempArray.sort()))
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input />
<p></p>

2

2 Answers 2

1

you can do something like this

const myArray = ['testB', 'testD', 'testC', 'dtest', 'cTest']
let tempArray = []

$('input').on('input', function() {
  
  const val = $(this).val().toLowerCase()
  tempArray = myArray.filter(a => a.toLowerCase().includes(val))
  //I want it to write ["testB","testC","testD", "cTest", "dtest"]
  const startsWith = (string, value) => string.substring(0, value.length).toLowerCase() === value
 
  $('p').html(JSON.stringify(tempArray.sort((a, b) => {
      const aStartsWith = startsWith(a, val)
      const bStartsWith = startsWith(b, val)

      if( aStartsWith && !bStartsWith){
        return -1
      }else if (!aStartsWith && bStartsWith){
        return 1;
      }
     
      return b > a?-1:1
  })))
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input />
<p></p>

edit Tried with the array @seriously said that fails but it seems to work fine

const myArray = ['the big bang theory', 'the office', 'top gun 2 maverick', 'the man from toronto', 'the bad guys']
let tempArray = []

$('input').on('input', function() {
  
  const val = $(this).val().toLowerCase()
  tempArray = myArray.filter(a => a.toLowerCase().includes(val))
  //I want it to write ["testB","testC","testD", "cTest", "dtest"]
  const startsWith = (string, value) => string.substring(0, value.length).toLowerCase() === value
 
  $('p').html(JSON.stringify(tempArray.sort((a, b) => {
      const aStartsWith = startsWith(a, val)
      const bStartsWith = startsWith(b, val)

      if( aStartsWith && !bStartsWith){
        return -1
      }else if (!aStartsWith && bStartsWith){
        return 1;
      }
     
      return b > a?-1:1
  })))
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input />
<p></p>

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

6 Comments

Remember that, as I quote from the docs of Array.prototype.sort(), “A comparator conforming to the constraints above will always be able to return all of 1, 0, and -1, or consistently return 0.”. So, for completeness, you should convert the last ternary operator into ifs.
@CcmU you're right but is pretty pointless in this case given that if the the string are equals it does't matter which come first
This fails!! Try setting myArray = ['the big bang theory', 'the office', 'top gun 2 maverick', 'the man from toronto', 'the bad guys']
@seriously what do you mean with it fails? I tried to change with the array as you said and it seems to work fine
@R4ncid no it doesn't the sorted array returns ['the bad guys', 'the man from toronto', 'the big bang theory', 'the office', 'top gun 2 maverick' ]
|
0

The key point of sort is compare function. For element a and b, which one has higher priority? There are three principe as your description:

  1. element contains search string has higher priority then not;
  2. if both element contain the search string, the lower index has higher priority;
  3. if index of search string is the same, then compare the two string element, with > operator.

If only want items contain the search value, you can add a filter before sort.

var search = 'test';

function compare(a, b) {
  var indexA = a.indexOf(search);
  var indexB = b.indexOf(search);
  
  if (indexA === indexB) {
    return a > b ? 1 : -1;
  }
  if (indexA === -1) {
    return 1;
  }
  if (indexB === -1) {
    return -1;
  }
  return indexA > indexB ? 1 : -1;
}

var arr = ['testB','AString', 'somthing', 'testC', 'testD', 'test1', 'Ctest', 'Atest', 'ADtest', 'ABtest'];

// filter search value before sort
function searchResult(arr) {
  return arr.filter(item => item.includes(search)).sort(compare);
}

console.log('result:', arr.sort(compare));
console.log('searchResult:', searchResult(arr));

2 Comments

if your set var search = 'a'; and run your function the return array will have items that don't even include the char a
@seriously If only want items contains search value, you can add a filter before sort. Updated my answer.

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.