Procedure for distributing proportions

Imagine having an object like this:

 const data = {
      bills: 10,
      rent: 40,
      food: 50,
    }

The total is 100 (or 100%).

If we update the bills to a value of 20, the other properties should adjust accordingly, for example:

{
 bills: 20,
 rent: 30,
 food: 50,
}

or

 {
   bills: 20,
   rent: 35,
   food: 45,
 }

it varies.

A code snippet I created often causes one property to dip below zero because the sum becomes 102 instead of 100. Here's the problematic code: https://i.sstatic.net/RmVjb.png

The code snippet is as follows:

 allocatePercentage(dataName, percentage) {
    const curr = this.data[dataName];
    this.data[dataName] = percentage;
    if (percentage === 100) {
      Object.keys(this.data).filter(key => key !== dataName).forEach(dataKey => {
        this.data[dataKey] = 0;
      });
    } else {
      const {[dataName]: current, ...rest} = this.data;
      Object.keys(rest).forEach(key => {
        this.data[key] = this.data[key] - ((percentage - curr) / Object.keys(rest).length);
      });
    }
}

Usage example:

allocatePercentage('bills', 20);

Assuming the object looks like this:

{
  bills: 10,
  rent: 40,
  food: 50,
}

for rent:

data['rent'] = 40 - ((20 - 10) / 2) // 35

for food:

data['food'] = 50 - ((20 - 10) / 2) // 45

Why does it sometimes result in a negative % value? (as shown in the photo)

How can I avoid this and accurately distribute the percentage?

Answer №1

Is it possible that your solution is 20/36/44? One could find the difference between 100 and the original value, then use that as a multiplier. While ES6 magic is trendy, sometimes understanding things in a traditional way can be beneficial.

{
  "bills": 20,
  "rent": 36,
  "food": 44
}

The reallocate function (shown below) should be invoked like this:

reallocate(data, 'bills', 20); // This modifies data directly and returns result

I created a makeshift function called testFn to handle function calls with arguments and display results in the console, including a check for total percentage.

const DEBUG = true;
const valuesEqual = (obj, expected) => Object.values(obj)
  .reduce((acc, v) => acc + v, 0) === expected;
const testFn = (fn, ...args) =>
  (res => console.log(JSON.stringify(res), '//', valuesEqual(res, 100)))
  (fn(...args));

const data = { bills: 10, rent: 40, food: 50 };

const reallocate = (categories, category, value) => {
  const oldVal     = categories[category] || 0,
        newValue   = categories[category] = value,
        other      = 100 - oldVal,
        diff       = newValue - oldVal,
        multiplier = (other - diff) / other;
  for (const cat in categories) {
    if (cat !== category) {
      categories[cat] = Math.round(categories[cat] * multiplier);
    }
  }
  return categories;
}

testFn(reallocate, { ...data }, 'bills', 20);         // Update - increment
testFn(reallocate, { ...data }, 'bills', 5);          // Update - decrement
testFn(reallocate, { ...data }, 'entertainment', 10); // Create
testFn(reallocate, { ...data }, 'bills', 0);          // Update - min
testFn(reallocate, { ...data }, 'bills', 100);        // Update - max
.as-console-wrapper { top: 0; max-height: 100% !important; }

Answer №2

Consider it in this way:

Expenses = 150
Rent = 30
Groceries = 20

If expenses increase to 200,
Expenses = 200
Rent = 30 - (200-150)/2 = 15
Groceries = 20 - (200-150)/2 = 10

Therefore, the distribution may not be evenly split. It is important to address situations where any expense category becomes negative or reaches zero.

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

The utilization of ES Modules within a Next.js server.js

After reviewing a few examples in the Next.js repository, I came across: https://github.com/zeit/next.js/tree/master/examples/custom-server-express https://github.com/zeit/next.js/tree/master/examples/custom-server-koa I observed that these examples ut ...

`In NestJS Nested Schema, the @Prop decorator and mongoose options are not applied as expected

I'm currently working on constructing a Schema that includes a nested object. I am trying to define default values and required properties within the nested object, but it seems like the options I set are being ignored. task.entity.ts @Schema() expor ...

Connecting JavaScript and PHP strings

My goal is to transfer a JavaScript string to a PHP processing script and compare them. Upon successful match, I intend to conduct a simple validation process and if it passes, send an email notification. To provide context, below is a snippet of my curre ...

Unable to invoke the jQuery datetimepicker function within a personalized directive

I have created a unique time picker directive in AngularJS to display a datetimepicker. app.directive("timePicker", function() { return { restrict: "A", link: function(scope, elem, attrs) { / ...

Is there a way to execute a javascript function that is located outside of my Angular application without having to import it?

I need to be able to trigger a JavaScript function that is located outside of my Angular app when a button is clicked. Unfortunately, it seems that importing the JavaScript directly into my Angular app isn't feasible for this task. The platform I am ...

Issues with JQuery Radio button selection in Internet Explorer 6

Here is some code that I am working with: <input type="radio" name="HotelSearch_Measure" value="Miles"> <input type="radio" name="HotelSearch_Measure" value="KM"> While this code functions properly in IE9, Chrome, and Firefox, it does not wor ...

Using jQuery to create a flawless animation

I am currently working on an animation project, and I have shared my progress on jsfiddle. Below is the code snippet I have utilized: /* JavaScript: */ var app = function () { var self = this; var allBoxes = $('.box&apos ...

Storing external API requests in create-react-app's service worker for faster retrieval

I'm in the process of transforming a React web application into a PWA (Progressive Web App). I've made the necessary change in the index.js file - serviceWorker.register();. Everything is functioning properly as I can access the home page and as ...

Validating multiple conditions in Typescript by passing them as function parameters

As a beginner in TS/JS, I am looking to validate multiple conditions passed as arguments to a function. For instance, currently I am verifying the user role name, but in the future, I may need to check other conditions. validateUserDetails(): Promise< ...

Managing a digital timepiece within a multiplayer gaming environment

I'm currently developing a fast-paced game where players control a block resembling a clock. To accurately calculate the time taken by each player to make moves, I store the start time of the game and record the timestamp of every move in the databas ...

Encountering issues with resolving dependencies in webdriverIO

I'm attempting to execute my WebdriverIo Specs using (npm run test-local) and encountering an error even though I have all the necessary dependencies listed in my package.json as shown below: [0-2] Error: Failed to create a session. Error forwardin ...

Solving TypeScript Error in React for State Destructuring

Recently, I've been working on creating a React component for AutoComplete based on a tutorial. In my development process, I am using Typescript. However, I encountered an issue while trying to destructure the state within the render suggestions metho ...

What's preventing this function from deducing the type?

I'm currently utilizing the "openapi-typescript" tool to automatically generate all the types based on my swagger server specifications. In this process, I have created a Type called "GetUrls" which contains all the keys associated with the "get" meth ...

Animating a CSS shape with the .animate method

I need help creating a dynamic graphic for my school project using css, jquery, and html. I want to make a rectangle that moves across the screen, but I'm having trouble getting it to work properly. Despite trying different variations of the animate f ...

What is the best way to incorporate setTimeout in a loop using Coffeescript?

window.onload = -> boxOrig1 = 10 boxOrig2 = 30 canvasW = 400 canvasH = 300 ctx = $("#canvas")[0].getContext('2d'); draw = (origin,dimension) -> ctx.clearRect(0, 0, canvasW, canvasH) ctx.fillStyle = 'rgb(200,0 ...

"Utilizing Node.js and Express to return JSONP data based on

For some reason, my Express application is giving me a strange result when using res.jsonp. It looks like this: /**/ typeof jsonp1406719695757 === 'function' && jsonp1406719695757({"published":true,"can_add_to_cart":true,"updated_at":"20 ...

Scrolling to an id within dynamically loaded content using jQuery after an ajax request

After loading content via ajax, I am unable to scroll to the item, as the page remains at the top. Strangely, when I refresh the page dynamically with content caching enabled, the page scrolls to the desired target. var startPageLoader = function( pid, si ...

This is my first experience with a Vue/webpack application, and surprisingly, there is no webpack

I am facing an issue with my app not properly loading css files. I suspect it has something to do with the fact that my app is utilizing webpack, but I am unable to locate a webpack.config.js file in the root directory. Instead, I have found webpack.base. ...

Discovering the Longest Oscillating Subsequence's Length

I am attempting to create a straightforward recursive definition that identifies the length of the longest oscillating subsequence within an array. My approach involves examining both the X[i] and X[i-1] elements, comparing them, and updating a counter a ...

Unexpected token error on an optional property in Visual Studio Code

I encountered a problem with a project I cloned. Below is the code snippet created using this project: https://github.com/enuchi/React-Google-Apps-Script export interface Vehicle { wheels: number; insurance?: string; } export default class Car { whe ...