Organizing a JavaScript array by comparing objects with varying key-value pairs

Here is an array that needs to be sorted:

var joins = [
  {
    "joinType": "INNER JOIN",
    "joinTableName": "country",
    "joinColumnName": "id",
    "foreignTableName": "state",
    "foreignColumnName": "country_id",
    "index": 1
  },
  // More objects in the array...
]

This code is used to sort the array:

joins.sort((a, b) => {
  if (a.foreignTableName === b.joinTableName) return 1;
  else if (a.joinTableName === b.foreignTableName) return -1;
  else return 0;
});

The resulting sorted array is displayed below.

// Sorted array here

An issue has been identified with the sorting logic used. It does not produce the expected order of elements based on the index values. Can you identify the problem?

Additional context: This sorting operation is part of creating a MySQL query statement using object field definitions from another system's database. This specific step pertains to generating the JOIN subclause.

Desired output:

// Expected sorted array

Answer №1

One possible approach involves assigning a unique level to each object based on its position within a linked list structure. This level is determined by the index of the root ancestor of the object and the depth of the object within the linked list. By introducing this new lvl property, we can then easily sort the objects based on this level. While this method may not be the most efficient in terms of performance, it could still meet your requirements.

var joins = [
  {
    "joinType": "INNER JOIN",
    "joinTableName": "country",
    "joinColumnName": "id",
    "foreignTableName": "state",
    "foreignColumnName": "country_id",
    "index": 1
  },
  {
    "joinType": "INNER JOIN",
    "joinTableName": "state",
    "joinColumnName": "id",
    "foreignTableName": "city",
    "foreignColumnName": "state_id",
    "index": 2
  },
  {
    "joinType": "INNER JOIN",
    "joinTableName": "city",
    "joinColumnName": "id",
    "foreignTableName": "address",
    "foreignColumnName": "city_id",
    "index": 3
  },
  {
    "joinType": "INNER JOIN",
    "joinTableName": "address",
    "joinColumnName": "id",
    "foreignTableName": "user",
    "foreignColumnName": "address_id",
    "index": 4
  },
  {
    "joinType": "INNER JOIN",
    "joinTableName": "user_status",
    "joinColumnName": "id",
    "foreignTableName": "user",
    "foreignColumnName": "status_id",
    "index": 5
  }
];

// Find the object with the table a foreign key is referencing.

const findParent = (fTable) => joins.find(x => x.joinTableName === fTable);

// Recursive method that assigns a level to an object based on the position
// they have on the linked list they belong to.

const getLevel = (fTable, index, lvl) =>
{
    let parent = findParent(fTable);
    return (fTable && parent) ?
           getLevel(parent.foreignTableName, parent.index, lvl + 1) :
           index + "-" + lvl;
}

// Maps the input data to adds the level property to each object.

let newInput = joins.map(obj =>
{
    obj.lvl = getLevel(obj.foreignTableName, obj.index, 0);
    return obj;
});

// Sorts the new generated data based on the level property. Since the
// lvl property is a string, we use "localeCompare()" to compare.

let sortedInput = newInput.sort((a, b) => a.lvl.localeCompare(b.lvl));

// Shows the sorted data.

console.log(sortedInput);

Answer №2

After exploring the functionality of Array.prototype.sort, I decided to experiment with a different approach using bubbleSort to identify any issues.

During each iteration, bubbleSort selects the leftmost element in the unsorted array as the "bubble" and attempts to move it one step to the right at a time. If the element is smaller than its neighboring element on the right, then the right neighbor becomes the new "bubble". This process continues until the largest element reaches the rightmost position among the unsorted elements.

The challenge arises when the elements in my specific dataset are not always comparable to each other. There isn't a clear "biggest" element that can be bubbled to the rightmost position due to partial orderability within the set. While some elements can be ordered, others cannot be compared directly.

To address this issue, I formulated an alternative solution: sorting the orderable elements into segments or chains before merging them together. This modified method, referred to as mergeSort, deviates from the traditional merge-sort algorithm but serves the purpose effectively.

function mergeSort(arr, compFn) {
  let res = [];
  while (arr.length > 0) {
    res = res.concat(makeChain(arr.splice(0, 1)[0], compFn));
  }
  return res.filter(n => n);

  function makeChain(obj, compFn) {
    let res = [obj];
    for (let i = 0; i < arr.length; i++) {
      if (isEmpty(arr[i])) return;
      let flag = compFn(obj, arr[i]);
      if (flag < 0) {
        res = res.concat(makeChain(arr.splice(i, 1)[0], compFn));
      } else if (flag > 0) {
        res = makeChain(arr.splice(i, 1)[0], compFn).concat(res);
      }
    }
    return res;
  }

}

Subsequently, I utilized the same compareFunction for ordering:

joins = mergeSort(joins, (a, b) => {
  if (a.foreignTableName === b.joinTableName) return 1; //b has higher precedence
  else if (a.joinTableName === b.foreignTableName) return -1; //a has higher precedence
  else return 0; //no change needed
});

This implementation successfully produced the desired sorted array outcome.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Learn how to easily convert a string to an Object in Vue by utilizing Json.parse

My goal is to convert the input value from the input element into an Object When I use JSON.parse() to convert the internData value, it doesn't turn the string into an Object as expected. Interestingly, performing the same operation in the browser c ...

Adjust the clarity of the elements within my HTML document

I have been working on creating a login page that will appear in front of the main webpage. Through my online research, I discovered a technique to blur the main webpage background until the user logs in. Below is the code snippet: HTML: <div id="logi ...

Unable to remove spaces in string using Jquery, except when they exist between words

My goal is to eliminate all white spaces from a string while keeping the spaces between words intact. I attempted the following method, but it did not yield the desired result. Input String = IF ( @F_28º@FC_89º = " @Very strongº " , 100 , IF ( @F_28 ...

What are the ways in which an array can interact with the conditional operator?

In an effort to address the unnoticed change in my previous post, I have decided to retell the story and make improvements. My goal is to provide a more concise version of the code snippet presented below: #include <cstddef> #include <type_traits ...

What is preventing ShowViaLink() from functioning properly in Firefox and Internet Explorer?

I am facing an issue with my webpage where the navigation does not work on Firefox or IE, but it works perfectly fine on Chrome. I suspect that the problem lies in this code, as when I made changes to it, the navigation stopped working on Firefox & IE: ...

[webpack]: npm ERROR! Call stack size limitation exceeded

While trying to install webpack using npm i -D webpack, an error is encountered as shown below. npm ERR! Maximum call stack size exceeded npm ERR! A complete log of this run can be found in: npm ERR! /Users/shobhuiy1/.npm/_logs/2019-02-05T10_31_29_46 ...

I'm experiencing difficulties loading data using AJAX

I'm facing an issue with an old script that used to load IP from an xml file. Everything was running smoothly until about six months ago when I tried to use it again and encountered some problems. I'm not sure what went wrong. Could there have be ...

What steps should be taken to enable bidirectional functionality for this slider control?

My range slider is currently only working in a single direction (to the right) and it's also dragging out of its parent container (#volume). How can I resolve this issue? I have included a demo fiddle link for reference. Markup <div id="volume"& ...

Retrieve specific content upon the loading of a webpage

I've been working on a function that detects a value and performs some operations with it. However, I'm running into an issue where I can't retrieve the value when the page initially loads, but I can access it after selecting a value. How ca ...

Dealing with Objects and Arrays in React Native: Best Practices

I'm in the process of developing a react native app for my college studies! I'm utilizing an external API as a data source, but I'm encountering a problem. Sometimes the data is returned in a single object format, and other times it's i ...

An issue arose when executing a script in elastic search, resulting in a gateway timeout error

Encountered a 504 Gateway timeout error while executing a script in elastic search. { "query": { "bool": { "filter": { "script": { "script": " doc['creted_date'].date.getMonthOfYear() == 12 " ...

Using Three.js to create a distorted texture video effect

Check out the example linked here for reference: In this particular project, there are two cylinders involved - an outer cylinder with an image texture and an inner cylinder with a video texture. Once the second cylinder is created and added to the scene, ...

Setting up Webpack with a Node.js backend

After successfully creating a structured outline for my React App, I have now uploaded the code to Github for easy access: https://github.com/KingOfCramers/React-App-Boilerplate. To launch this React server using Node and Express, I found a helpful guide ...

Once the email has been successfully sent and the modal has been called, the submit button should be deactivated permanently

Hello everyone, I need some help with a programming challenge I'm facing. I am trying to permanently disable the 'Approve' button, which sends an email using PHP and triggers a modal when clicked. I've attempted to use local storage to ...

Troubleshooting issue with Bootstrap and React: navbar toggle function not functioning properly

Hey there, I've encountered an issue while working with my stateless component and trying to integrate Bootstrap into my code. Everything was good when I coded it in vanilla HTML/CSS and JS, but now I'm having trouble with the data-target="#navig ...

Enhance your Node text with captivating font ligatures

I'm facing an issue with font ligatures in a specific sentence. The sentence that's causing the problem is: Verizon is sunsetting BlueJeans as the platform struggled to gain traction against rival services in the video conferencing market I ha ...

Utilizing Odometer to pass a variable to jQuery

I'm interested in incorporating a jQuery odometer into a master page to display dynamic information. I found a helpful resource for this at this link. To achieve this, I need to fetch data from a SQL Server database using C# and then pass it to the J ...

In Typescript, encountering a member of a union type with an incompatible signature while utilizing the find method on an array of

I need to verify if a specific value exists within an array of objects. The structure of my array is as follows: [ 0: { id: 'unique_obj_id', item: { id: 'unique_item_id', ... }, ... }, 1: {...} ] The objects in the ar ...

Replace all without worrying about capitalization

Does anyone have a solution for a case-insensitive replacing function in JavaScript? For instance, if I want to replace 'is' with 'as', it should work similar to this: 'This iS IIS'.replaceAll('is', 'as'); ...

What is the best way to retrieve a MariaDB query result using Node.js?

I've been delving into the world of Node.js to enhance my web development skills, particularly in retrieving data from a mariaDB using SELECT queries and converting it into JSON for client requests. Despite scouring the internet and stackoverflow, I h ...