Retrieve specific elements from an array based on the other elements present in the array

I am working with a result set that consists of various combinations from the following data structure:

[ ["1st", "FELONY"], ["2nd", "FELONY"],  ["3rd", "FELONY"], ["1st", "MISDEMEANOR"], ["2nd", "MISDEMEANOR"], ["3rd", "MISDEMEANOR"]]  

For example, it could be:

[  ["2nd", "FELONY"], ["2nd", "MISDEMEANOR"], ["1st", "MISDEMEANOR"]]           

Or:

[ ["1st", "MISDEMEANOR"], ["2nd", "MISDEMEANOR"]]    

Or any other combination and order of elements.

If the array contains a subarray with FELONY, my aim is to disregard MISDEMEANOR elements and retrieve "1st" if available, then "2nd", finally "3rd". If there are no FELONY elements in the array, I want to fetch the "1st" MISDEMEANOR element if present, then "2nd", finally "3rd".

This is how I have approached the problem:

var arr = [ ["1st", "FELONY"], ["3rd", "FELONY"], ["2nd", "FELONY"], ["2nd", "MISDEMEANOR"], ["3rd", "MISDEMEANOR"], ["1st", "MISDEMEANOR"]];
for(var i = 0, found = [], fel1 = false, fel2 = false, fel3 = false, mis1 = false, mis2 = false, mis3 = false; i < arr.length; i++) {
   if(arr[i][0] == "1st" && arr[i][1] == "FELONY"){
       found = arr[i];
       fel1 = true;
   } else if (arr[i][0] == "2nd" && arr[i][1] == "FELONY" && !fel1){
       found = arr[i];
       fel2 = true;
   } else if (arr[i][0] == "3rd" && arr[i][1] == "FELONY" && !fel1 && !fel2){
       found = arr[i];
       fel3 = true;
   } else if (arr[i][0] == "1st" && arr[i][1] == "MISDEMEANOR" && !fel1 && !fel2 && !fel3){
       found = arr[i];
       mis1 = true;
   } else if (arr[i][0] == "2nd" && arr[i][1] == "MISDEMEANOR" && !fel1 && !fel2 && !fel3 && !mis1){
       found = arr[i];
       mis2 = true;
   } else if (arr[i][0] == "3rd" && arr[i][1] == "MISDEMEANOR" && !fel1 && !fel2 && !fel3 && !mis1){
       found = arr[i];
       mis3 = true;
   }
}

if( match && (match[2] == "FELONY" || match[2] == "MISDEMEANOR") && (found[2] != "FELONY" && found[1] != "1st") ) {
            found = [ match[1], match[2], match[3], match[4] ]
            console.log("FOUND! " + found[1]);
} else {
            console.log(`could not parse ${chargesList[i]}`);
}

console.log(JSON.stringify(found));

The current solution works but seems a bit messy. Are there cleaner ways to achieve this using EcmaScript 6 features?

Answer №1

To efficiently navigate through your array with minimal repetition, it is best to avoid long chains of if/else statements. One effective approach is to implement a scoring system where each item is assigned a unique score and the highest score indicates the desired item. There are numerous ways to achieve this, but one straightforward method involves assigning numerical values to 'felony' and 'misdemeanor' such that they are higher than any other categories. The 10s place represent felony/misdemeanors, while the 1s digit represents the ranking within those categories. By iterating through the array once using this scoring system, you can easily identify the item with the highest score:

let scores = {
  FELONY: 20,
  MISDEMEANOR: 10,
  '1st': 3,
  '2nd': 2,
  '3rd': 1
}

let arr = [["2nd", "FELONY"],["2nd", "MISDEMEANOR"], ["1st", "MISDEMEANOR"],["1st", "FELONY"]]

let highest = 0, result
for (item of arr) {
  let score = item.reduce((a, c) => a + scores[c], 0)
  if (score > highest) {
    highest = score
    result = item
  }
}
console.log(result)

This method also facilitates easy modifications to preferences or the addition of new categories without relying on alphabetical order for sorting.

Answer №2

If you're looking for a straightforward solution, you can consider the following:

function sortArray(a) {
  return [...a].sort(([aa, ab], [ba, bb]) => (ab + aa).localeCompare(bb + ba))
}

To implement this method, simply do the following:

const [selected] = sortArray(arr)

Key points to remember:

  • Copying the array using [...a] is necessary because the sort function modifies the original array
  • This specific sorting logic assumes that in your case, FELONY should come before MISDEMEANOR, and numbers like 1st, 2nd, etc., are involved
  • Although not the most efficient approach, it should suffice for your current requirements

If you need to sort other strings differently, you can utilize a lookup table as shown below:

const lookup = {
  FELONY: 1,
  MISDEMEANOR: 2,
  ...
}

sort(... => (lookup[ab] + lookup[aa]).localeCompare(...))

Answer №3

Unsure whether the solution presented here is more sophisticated or effective than what you already have - I'll defer to the expertise of JavaScript professionals to provide feedback. Nevertheless, this is my attempt:

It should be noted that the following rough assumptions were taken into consideration :-|

  1. The initial element of the inner array (sub-array) always begins with ordinal numbers like 1st, 2nd, etc.

    1.1 The subsequent characters after the number are single digits (not exceeding 9).

var sampleArray = [ ["1st", "FELONY"], ["2nd", "FELONY"],  ["3rd", "FELONY"], ["1st", "MISDEMEANOR"], ["2nd", "MISDEMEANOR"], ["3rd", "MISDEMEANOR"]] 
// var sampleArray = [["2nd", "FELONY"], ["2nd", "MISDEMEANOR"], ["1st", "MISDEMEANOR"]]
// var sampleArray = [["2nd", "FELONY"], ["2nd", "MISDEMEANOR"], ["1st", "MISDEMEANOR"]]

var reducedArray = sampleArray.reduce((a,b) => a.concat(b))

// Step 1: Filter out any instances of FELONY.
let result = [];
if(reducedArray.includes("FELONY")) {
sampleArray.forEach(a => {if(a.includes("FELONY")) {
    result.push(a);
}})
}else{
result = sampleArray;
}

// Step 2: Sort and retrieve the first element.

result.sort((a,b) => {
if(a[0].substring(0) < b[0].substring(0)) {
    return -1;
} else if(a[0].substring(0) > b[0].substring(0)){
    return 1;
}
return 0;
})

console.log(result[0]); 

Answer №4

Transforming your structure into an object structure can easily accommodate any number of people or rankings in the future.

const list = [ ["1st", "FELONY"], ["2nd", "FELONY"],  ["3nd", "FELONY"], ["1st", "MISDEMEANOR"], ["3rd", "MISDEMEANOR"]]  

let obj = {}
list.forEach((item, index) => {
  obj = {
    ...obj,
    [item[1]] : {
       ...obj[item[1]],
       [item[0]]: index,
    }
  }
})

console.log(obj)

You can observe that for the given list above, our object appears as follows:

{
  "FELONY": {
    "1st": 0,
    "2nd": 1,
    "3nd": 2
  },
  "MISDEMEANOR": {
    "1st": 3,
    "3rd": 4
  }
}

From this object structure, we can now retrieve the required value with ease.

const obj = {
  "FELONY": {
    "1st": 0,
    "2nd": 1,
    "3nd": 2
  },
  "MISDEMEANOR": {
    "1st": 3,
    "3rd": 4
  }
}

let nameToLookFor = 'FELONY';
if (!obj[nameToLookFor]) {
  nameToLookFor = 'MISDEMEANOR'
}

const found = 
  obj[nameToLookFor]['1st'] || obj[nameToLookFor]['2nd'] || obj[nameToLookFor]['3rd']);

console.log(found)

const obj = {
  "FELONY": {
    "1st": 0,
    "2nd": 1,
    "3nd": 2
  },
  "MISDEMEANOR": {
    "1st": 3,
    "3rd": 4
  }
}

let nameToLookFor = 'FELONY';
if (!obj[nameToLookFor]) {
  nameToLookFor = 'MISDEMEANOR'
}


const found = 
  obj[nameToLookFor]['1st'] || obj[nameToLookFor]['2nd'] || obj[nameToLookFor]['3rd'];

console.log(found)

Answer №5

function organizePenalties(data){
    const   felonies = data.filter(subArr => subArr[1] == "FELONY"),
            misdemeanors = data.filter(subArr => subArr[1] == "MISDEMEANOR");

    function sortData(arr){
      const sortedArray = [];

      for(let i = 0; i < arr.length; i++){
        sortedArray[arr[i][0][0] - 1] = arr[i];
      }

      return sortedArray[0] || sortedArray[1] || sortedArray[2];
    }

    return felonies.length > 0 ? sortData(felonies) : sortData(misdemeanors);
}
  • To begin with, I suggest using the ES6 filter array method to categorize felonies and misdemeanors. This method creates an array with elements that match a specified condition, in this case either "FELONY" or "MISDEMEANOR"
  • I then implemented a custom sorting function that takes in an array, iterates through it, and assigns each element to a new array based on a specified position. By extracting and adjusting the numerical value, we accurately place each item in its corresponding index in the newarr.
  • The final step of our custom sorting function is to return the first item encountered, depending on the input data. For example, if the input data is [["3rd", "MISDEMEANOR"], ["2nd", "MISDEMEANOR"]], there would be no item at index 0, but one would exist at index 1, making the use of the || operator perfect for this scenario.
  • Lastly, a ternary operation checks whether there are any felonies by examining their length. If felony records are present, the function returns the sorted result for felonies; otherwise, it returns the sorted result for misdemeanors.

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

Difficulties encountered when trying to load liquid using Javascript

Having trouble loading the Shopify liquid object {{product.price | json}} into JS, as it's displaying NaN with the current code on the front end. Any suggestions on how to properly pass liquid into JS? I've tried two functions but neither seem t ...

"Exploring the World of Arduino with Structs

As a novice in Arduino programming, I am currently exploring the usage of structs. I am facing a challenge in declaring an array inside the struct and utilizing it effectively. Specifically, I am uncertain about how to declare and utilize arrays such as ...

Tips for refreshing an angularjs $scope using $.get jquery

Attempting to implement the code below using $scope: var scopes = "https://www.googleapis.com/auth/contacts.readonly"; setTimeout(authorize(), 20); function authorize() { gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: false}, h ...

Learn how to retrieve data by clicking on the previous and next buttons in FullCalendar using Vue.js

Seeking guidance on retrieving calendar data from the database for my Vue frontend, I have incorporated the fullcalendar API. Successfully able to retrieve data for the current week, however facing challenges when attempting to fetch data for the previous ...

Exploring the colors of legend navigation icons in Google Pie charts

Is there a way to customize the color of the navigation links in Google pie charts (specifically the blue text in the bottom right corner)? ...

How to create custom options in a JavaScriptMVC Controller's event listener?

When working with JavascriptMVC's Controller, they have a unique format for handling events Rather than using traditional jQuery methods $(function(){ $('#tabs').click(someCallbackFunction1) $('#tabs .tab').click(someCallback ...

Arrangement featuring two distinct types of tiles

Looking for a way to achieve this layout using just CSS or a combination of CSS and a little JS. Click on my avatar to see the reference image enlarged =) I've tried using floats and display options but haven't been successful. Take a look at htt ...

After successful login, the user will be automatically directed to the next page with

I am encountering challenges with a specific portion of my code. I am in the process of sending user information to the server, receiving a token from the user, and then aiming to redirect the user to a URL. However, despite the code entering the if stat ...

Placing a function within an array raises the question: why is the array's value represented as an integer?

There's something puzzling happening in my code. I've placed a setTimeout function inside an array, but when I check the contents of the array using console.log(arr), it only shows an integer value. How is this possible? See the code snippet belo ...

iPhone: Fixed position div disappearing

Currently, I am working on creating a mobile menu for my Joomla 3 site located at . The menu is functioning correctly on desktops, however, when attempting to view it on my iPhone, the menu slides in but remains invisible. Despite this, I can still tap on ...

Angular 4 with Universal: Implementing 404 Status Code in Header for /404 Page Component

After researching and reviewing numerous StackOverflow inquiries, I have come to the conclusion that headers are derived from responses served by servers, making it a non-issue. I attempted to rectify the situation from my server.ts file but unfortunately ...

Displaying a picture solely in a designated region

I created a basic menu using an unordered list: <ul class="courses"> <a href="#"> <li class="spinny"> <h3>Course Title</h3> <img class="rotateme" src="images/logo_transparent.png"/> </li& ...

troubles arise when using undeclared functions in javascript

Recently, I've been working on implementing a Javascript CountDown Timer triggered by a button click. The Javascript code is stored in an external file, as well as the CSS for styling the timer. The problem arose when I tried including the Javascript ...

When attempting to incorporate Jasmine into my current AngularJS/Bootstrap project, I encountered the error message stating

Currently, I am working on a group project that requires test coverage. The project utilizes npm and angularJS. To kick things off, I performed an npm install for jquery, jasmine, and angular-mocks. Since I'm relatively new to testing, I decided to st ...

Issue with BrowserRouter, improperly looping through the array using map

Encountering an issue with importing content in my React app project using <BrowserRouter>. Within the app, there are 3 Material-UI Tabs: /lights, /animations, /settings. <Switch> <Route path="/lights" component={LightsMenu} /> ...

Simultaneously, two identical messages arrived in the form of push notifications via FCM

I have been working on implementing WebPush notifications using Vue.js and FCM. However, when testing the functionality, I am facing an issue where instead of receiving just one notification from Firebase, TWO IDENTICAL PUSH NOTIFICATIONS are being receive ...

Updating the default color of selected text within a webpage's content

Is there a way to modify the default blue color that appears when content is selected on a webpage? I am wondering how to change this selection color to a custom color of choice. ...

Manipulate audio files by utilizing the web audio API and wavesurfer.js to cut and paste audio

I am currently working on developing a web-based editor that allows users to customize basic settings for their audio files. To achieve this, I have integrated wavesurfer.js as a plugin due to its efficient and cross-browser waveform solution. After prior ...

Looking for a personalized function to iterate through every displayed row and reduce the number of API requests made

UPDATE: Seeking guidance on consolidating functions and implementing a trigger. Within my spreadsheet, I manage rows 4-100 that represent customer service calls filtered from a "ServiceData" worksheet by selecting either a "Service Month" or "Service Day" ...

AngularJS/Ionic: Issue with HTTP GET requests not completing within a specified timeframe

Attempting to populate options with specific values instead of undefined, but encountering a delay in retrieving the values after the select box has finished loading. https://i.stack.imgur.com/SpEFP.jpg To illustrate, here is the HTML code snippet: < ...