Home > Blockchain >  Sorting an array of objects based on relevance of a key-value pair (JavaScript)
Sorting an array of objects based on relevance of a key-value pair (JavaScript)

Time:12-26

I have an array of objects shown below:

[
        {
            "title": "Rickenbacker Guitar",
            "desc": "A wonderful instrument for beginners",
            "price": 8,
            "filterid": 957255
        },

        {
            "title": "Cool Saxophone!",
            "desc": "Just a cool sax.",
            "price": 13,
            "filterid": 119203
        },

        {
            "title": "Grand Piano",
            "desc": "Just a piano!",
            "price": 28,
            "filterid": 118420
        },
        {
            "title": "Eastman Violin",
            "desc": "Great for Advanced level musicians",
            "price": 18,
            "filterid": 118437
        },

]

I also have a variable called filter, For this example, lets say that filter = 118437 I want the array of objects to be sorted based off of the filterid key (Where the filterid most closely matches the filter). Here is what I want the sorted JSON to look like:

// Sorted with filter of 118437
[
       {
            "title": "Eastman Violin",
            "desc": "Great for Advanced level musicians",
            "price": 18,
            "filterid": 118437 // This appears first since filterid matches exactly.
        },

        {
            "title": "Grand Piano",
            "desc": "Just a piano!",
            "price": 28,
            "filterid": 118420 // This comes next because it is the second closest match
        },

        {
            "title": "Cool Saxophone!",
            "desc": "Just a cool sax.",
            "price": 13,
            "filterid": 119203 // Comes next because 3rd closest match (has 11 in beginning)
        },

        {
            "title": "Rickenbacker Guitar",
            "desc": "A wonderful instrument for beginners",
            "price": 8,
            "filterid": 957255 // Comes last because the filterif doesnt match at all.
        } // If there are any more of the objects where filterid does not match at all, the order of them doesnt matter. (ie there is no preference to 999999 in comparision to 888888 since both dont match at all) 

]

I tried using Array.prototype.sort() method with a sorting function, but nothing that I did seemed to give me the result that I am looking for.

I cannot use JQuery, so it would be very helpful if the result can be achieved using vanilla JS

CodePudding user response:

You can calculate the priority using a code like that:

function getMatchValue(original, filterid) {
  // convert values to string
  const a = original.toString()
  const b = filterid.toString()

  let sum = 0

  for (let i = 0; i < a.length; i  = 1) {
    // if characters match
    if (a[i] === b[i]) {
      // characters at the beginning yield more value
      sum  = a.length - i
    }
  }
  
  return sum
}

I would think about using a fuzzy search algorithm (take look at fuse.js) and using a string as filterid

const data = [{
    "title": "Rickenbacker Guitar",
    "desc": "A wonderful instrument for beginners",
    "price": 8,
    "filterid": 957255
  },

  {
    "title": "Cool Saxophone!",
    "desc": "Just a cool sax.",
    "price": 13,
    "filterid": 119203
  },

  {
    "title": "Grand Piano",
    "desc": "Just a piano!",
    "price": 28,
    "filterid": 118420
  },
  {
    "title": "Eastman Violin",
    "desc": "Great for Advanced level musicians",
    "price": 18,
    "filterid": 118437
  },
]

const key = 118437

const sorted = [...data].sort((a, b) => {
  const aValue = getMatchValue(key, a.filterid)
  const bValue = getMatchValue(key, b.filterid)
  return aValue < bValue ? 1 : aValue > bValue ? -1 : 0
})

console.log(sorted)

function getMatchValue(original, filterid) {
  const a = original.toString()
  const b = filterid.toString()

  let sum = 0

  for (let i = 0; i < a.length; i  = 1) {
    if (a[i] === b[i]) {
      sum  = a.length - i
    }
  }

  return sum
}

CodePudding user response:

Maybe this is a better fit?

The comparison function in .sort() looks at the distance of each value from the given filter value and sorts accordingly: (numerically) closer matches come first.

const data = [{
    "title": "Rickenbacker Guitar",
    "desc": "A wonderful instrument for beginners",
    "price": 8,
    "filterid": 118440
  },

  {
    "title": "Cool Saxophone!",
    "desc": "Just a cool sax.",
    "price": 13,
    "filterid": 119203
  },

  {
    "title": "Grand Piano",
    "desc": "Just a piano!",
    "price": 28,
    "filterid": 118420
  },
  {
    "title": "Eastman Violin",
    "desc": "Great for Advanced level musicians",
    "price": 18,
    "filterid": 118437
  },

];
const filter = 118437 ;
const sorted = data.sort((a, b) => Math.abs(a.filterid-filter)-Math.abs(b.filterid-filter));
console.log(sorted)

  • Related