Increase the value of a property within an array of objects based on certain conditions

My task involves incrementing the rank value by one until the name property changes. I am utilizing the page and rank properties to track when this change occurs.

In addition, I want to increment it once whenever the type is not equal to none, and then resume incrementing when it becomes equal to none again.

I have almost achieved this using the provided code snippet, however, I seem to be lagging behind by one step. When the type transitions back to none, it fails to increment accordingly.

The desired output:

[
  { name: 'car', rank: 1, page: 1, type: 'other' },
  { name: 'car', rank: 2, page: 1, type: 'none' },
  { name: 'car', rank: 3, page: 2, type: 'none' },
  { name: 'car', rank: 4, page: 2, type: 'none' },

  { name: 'bike', rank: 1, page: 1, type: 'none' },
  { name: 'bike', rank: 2, page: 1, type: 'none' },
  { name: 'bike', rank: 3, page: 2, type: 'something_else' },
  { name: 'bike', rank: 3, page: 2, type: 'something_else' },
  { name: 'bike', rank: 3, page: 3, type: 'something_else' },
  { name: 'bike', rank: 4, page: 3, type: 'none' },

  { name: 'moto', rank: 1, page: 1, type: 'not_none' },
  { name: 'moto', rank: 1, page: 1, type: 'not_none' },
  { name: 'moto', rank: 2, page: 2, type: 'none' },
  { name: 'moto', rank: 3, page: 2, type: 'none' },

  { name: 'bus', rank: 1, page: 1, type: 'none' },
  { name: 'bus', rank: 2, page: 1, type: 'none' },
  { name: 'bus', rank: 3, page: 2, type: 'none' }
]

Answer №1

Ensuring the rank increases when either the current or previous type is "none" is essential. Accessing the previous type can be done through the third and fourth arguments in the reduce function.

const data = [
  { name: 'car', rank: 1, page: 1, type: 'none' },
  { name: 'car', rank: 2, page: 1, type: 'none' },
  { name: 'car', rank: 1, page: 2, type: 'none' },
  { name: 'car', rank: 2, page: 2, type: 'none' },
  { name: 'bike', rank: 1, page: 1, type: 'none' },
  { name: 'bike', rank: 2, page: 1, type: 'none' },
  { name: 'bike', rank: 1, page: 2, type: 'something_else' },
  { name: 'bike', rank: 2, page: 2, type: 'something_else' },
  { name: 'bike', rank: 1, page: 3, type: 'something_else' },
  { name: 'bike', rank: 2, page: 3, type: 'none' }, 
  { name: 'moto', rank: 1, page: 1, type: 'not_none' },
  { name: 'moto', rank: 2, page: 1, type: 'not_none' },
  { name: 'moto', rank: 1, page: 2, type: 'none' },
  { name: 'moto', rank: 2, page: 2, type: 'none' },
  { name: 'bus', rank: 1, page: 1, type: 'none' },
  { name: 'bus', rank: 2, page: 1, type: 'none' },
  { name: 'bus', rank: 1, page: 2, type: 'none' },
]

let counter = 1

const results = data.reduce((acc, obj, i, data) => {

  if (obj.page === 1 && obj.rank === 1) 
    counter = 0;

  obj.rank = [obj.type, data[i-1]?.type].includes('none') || !i ? ++counter : counter;

  acc.push(obj)
  return acc
}, [])

console.log(results)
.as-console-wrapper { max-height: 100% !important; top: 0; }

Answer №2

const information = [
  { name: 'car', rank: 1, page: 1, type: 'none' },
  { name: 'car', rank: 2, page: 1, type: 'none' },
  { name: 'car', rank: 1, page: 2, type: 'none' },
  { name: 'car', rank: 2, page: 2, type: 'none' },
  { name: 'bike', rank: 1, page: 1, type: 'none' },
  { name: 'bike', rank: 2, page: 1, type: 'none' },
  { name: 'bike', rank: 1, page: 2, type: 'something_else' },
  { name: 'bike', rank: 2, page: 2, type: 'something_else' },
  { name: 'bike', rank: 1, page: 3, type: 'something_else' },
  { name: 'bike', rank: 2, page: 3, type: 'none' }, 
  { name: 'moto', rank: 1, page: 1, type: 'not_none' },
  { name: 'moto', rank: 2, page: 1, type: 'not_none' },
  { name: 'moto', rank: 1, page: 2, type: 'none' },
  { name: 'moto', rank: 2, page: 2, type: 'none' },
  { name: 'bus', rank: 1, page: 1, type: 'none' },
  { name: 'bus', rank: 2, page: 1, type: 'none' },
  { name: 'bus', rank: 1, page: 2, type: 'none' },
]

let count = 1
let jump = false

const outcomes = information.reduce((acc, obj) => {

  if (obj.page === 1 && obj.rank === 1) {
    count = 0
    jump = false
  }
  if (obj.type !== 'none') {
    if (!jump) {
      jump = true
      count++
    }
  } else {
    jump = false;
    count++
  }
  
  obj.rank = count

  acc.push(obj)
  return acc
}, [])

console.log(outcomes)
.as-console-wrapper { max-height: 100% !important; top: 0; }

The condition can possibly be simplified to:

  if (obj.type === 'none' || !jump ) {
    jump = (obj.type !== 'none')
    counter++;
  }

Answer №3

After some consideration, I implemented a solution that takes into account whether the first object's type is not equal to none, ensuring that it still receives rank 1. I appreciate all the feedback from everyone and a special thank you to trincot for reminding me about the use of optional chaining

const data = [ { name: 'car', rank: 1, page: 1, type: 'other' }, { name: 'car', rank: 2, page: 1, type: 'none' }, { name: 'car', rank: 1, page: 2, type: 'none' }, { name: 'car', rank: 2, page: 2, type: 'none' }, { name: 'bike', rank: 1, page: 1, type: 'none' }, { name: 'bike', rank: 2, page: 1, type: 'none' }, { name: 'bike', rank: 1, page: 2, type: 'somethingelse' }, { name: 'bike', rank: 2, page: 2, type: 'somethingelse' }, { name: 'bike', rank: 1, page: 3, type: 'somethingelse' }, { name: 'bike', rank: 2, page: 3, type: 'none' }, { name: 'moto', rank: 1, page: 1, type: 'not_none' }, { name: 'moto', rank: 2, page: 1, type: 'not_none' }, { name: 'moto', rank: 1, page: 2, type: 'none' }, { name: 'moto', rank: 2, page: 2, type: 'none' }, { name: 'bus', rank: 1, page: 1, type: 'none' }, { name: 'bus', rank: 2, page: 1, type: 'none' }, { name: 'bus', rank: 1, page: 2, type: 'none' }, ]

let counter = 0

const relative = data.reduce((acc, obj, index, array) => {

  if (obj.page === 1 && obj.rank === 1) counter = 0
  if (obj.type === 'none' || array[index -1]?.type !== obj.type) counter++
  
  obj.rank = counter
  acc.push(obj)
  return acc
}, [])

console.log(relative)
.as-console-wrapper { max-height: 100% !important; top: 0; }

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

Sorting arrays of objects with multiple properties in Typescript

When it comes to sorting an array with objects that have multiple properties, it can sometimes get tricky. I have objects with a 'name' string and a 'mandatory' boolean. My goal is to first sort the objects based on age, then by name. ...

Incorporating unique HTML5/iframe widgets into your Facebook Timeline and Tab Pages

I have a unique widget that users can easily integrate into their websites using the HTML/iframe code generated by my app. Now, I am looking for a way to allow users to also add this widget to their Facebook Company Pages. The widgets are accessible th ...

Issue with initializing MdTable in Vue Material when fetching data

After encountering a null error while trying to fetch remote data to initialize the MdTable component, I shared my issue here. The data is retrieved from a MySQL database as part of a Laravel 5.6 API project. Upon thorough investigation, it seems that the ...

Start up a server using Angular along with Node.js and Express framework

I am encountering an issue with configuring Express as a server in my Angular application. The app loads without any issues when accessing the HOME route, but when trying to access another route, I receive an error message: Cannot GET / This is how I hav ...

What is the best way to include multiple entries in a select2 form using ajaxform?

select2/3.5.2/ I had to repost this because my initial post was not formatting correctly. The tools in use are: A select2 form field that allows searching through multiple records A bootstrap popup modal containing a form for entering a new record if i ...

The cookie is not displaying in the web browser

Why are my cookies not showing in the browser? I have tried multiple times, but even though the backend is sending the cookie, it is not being stored in the browser. I have also attempted to use different browsers like Chrome and Microsoft Bing. In Postma ...

What is the proper method for adding a file to formData prior to sending it to the server using a

I came across this tutorial on FormData, but I'm still trying to grasp how the formData object functions. Input Form Example: https://i.stack.imgur.com/h5Ubz.png <input type="file" id="file-id" class="w300px rounded4px" name="file" placeholder=" ...

Is there a way to retrieve data from a sealed JSON object using JavaScript?

The data is being fetched from the API and here is the response object: { "abc": [{ "xyz": "INFO 1", "pqr": "INFO 2" }, { "xyz": "INFO 3", "pqr": "INFO 4" } ] } We are lookin ...

How to determine button placement based on the content present on the page

I'm struggling to find the right CSS positioning for a button on my page. I want the button to stay fixed in a specific location, but when there's a lot of content on the page, I need it to adjust its position accordingly. Initially, I want the ...

What could be the reason why both the add and remove functions are unable to work simultaneously within a JavaScript function?

Hi there! I recently started diving into JavaScript and encountered a little hiccup. I've been working on a dice game where images change randomly whenever a button is clicked. The images transition from one to another, but I wanted to add a rolling ...

Create a constructor that takes in inputs and adds them to an array

My current challenge involves working with a class that has a constructor and utilizing it within an array. Unfortunately, when attempting to do so, I encounter an error. Here is the snippet of code in question: using System; class ClassA { public ...

Using JavaScript to Filter JSON Objects

After making a php ajax call, I have received the following JSON data that needs to be displayed to the users: JSON {"headers":{},"body":"{\"comuni\":[{\"datapresub\":\"08\/08 ...

Difficulty arises when trying to add various text fields to a collection

Lately, I've been making modifications to the Meteor1.3+React Todos app to familiarize myself with the basics, and I must say, it's been a smooth ride so far. However, I have encountered a roadblock. I want to incorporate an additional text field ...

Interactive Vue tree view featuring draggable nodes

I am currently working on creating a tree component in Vue.js, and I am facing challenges with implementing drag and drop functionality in the Tree component. I am unsure where to begin, as I have looked through similar code on GitHub but I am struggling t ...

The digest string for the crypto.pbkdf2Sync function is malfunctioning

I've been working on revamping the authentication system for an old application that previously ran on node 4.5, but I keep encountering an error whenever I attempt to log in. TypeError [ERR_INVALID_ARG_TYPE]: The "digest" argument must be one of type ...

Creating visual elements in Vue.js using an array structure

I attempted to use Vuejs to display a list of items, and the code snippet below is a simplified version of my attempt. Despite seeing the data in VueDevTool, I am unable to render it on the page. <template> <div> <h1>{{t ...

Transforming JQuery code into pure Javascript: Attaching an event listener to dynamically generated elements

After exhausting all available resources on stack overflow, I am still unable to find a solution to my problem. I am currently trying to convert the JQuery function below into Vanilla JavaScript as part of my mission to make web pages free of JQuery. How ...

"Looking for a way to automatically close the <li> tag in Vuejs when clicked outside

clickOutside: 0, methods: { outside: function(e) { this.clickOutside += 1 // eslint-disable-next-line console.log('clicked outside!') }, directives: { 'click-outside': { ...

Struggling with the alignment of pictures inside a container

I utilized the Instafeed.js library to fetch the three most recent images from an Instagram account. These images are loaded into a specific div and I successfully customized their styling according to my requirements. However, the current setup is quite s ...

Troubleshooting the Problem of Adding Class with jQuery Click

Good day, I've been struggling with this issue all day. Almost got it working but not quite there yet. The problem is that I need the corresponding paragraph (#p-1 etc) to remain highlighted once the thumbnail is clicked. I have customized a plugin fo ...