简体   繁体   中英

sorting two associative arrays/stacks

I am implementing an algorithm I designed and am exploring different approaches

This isn't a homework problem but I am going to explain it like one: lets say a merchant has bought inventory of apples on different days, and also sold some on different days. I want the weighted average timestamp of their current purchases.

I am storing this data object as timestamp string in epoch time, and quantity of apples. My dataset actually has the purchases and the sells in separate data sets, like so:

//buys
var incomingArray = {
  "1518744389": 10,
  "1318744389": 30
};

//sells
var outgoingArray = {
  "1518744480": 3,
  "1418744389": 5,
  "1408744389": 8
};

and I would like the outcome to show only the remainding incomingArray timestamp purchase pairs.

var incomingArrayRemaining = {
  "1518744389": 7,
  "1318744389": 17
};

Where you see there was one outgoing transaction for 3 apples at a later timestamp, therefore subtracting from 10. And there were 13 outgoing transactions before the buy of 10, but after the purchase of 30, so they only subtract from the 30.

Note, if more than 10 were transferred after 10, it would subtract from both 10 and 30. The number of apples can never be less than 0.

First, to accomplish my goals it seems that I need to know how many are actually still owned from the lot they were purchased in.

Instead of doing stack subtracting in the LIFO method, it seems like this has to be more like Tax Lot Accounting. Where the lots themselves have to be treated independently.

Therefore I would have to take the timestamp of the first index of the sell in the outgoing array and find the nearest older timestamp of the buy in the incoming array

Here is what I tried:

for (var ink in incomingArray) {
  var inInt = parseInt(ink);

  for (var outk in outgoingArray) {
    if (inInt >= 0) {
      var outInt = parseInt(outk);

      if (outInt >= inInt) {
        inInt = inInt - outInt;
        if (intInt < 0) {
          outInt = inInt * -1; //remainder
          inInt = 0;
        } //end if
      } //end if
    } //end if
  } //end innter for
} //end outer for

It is incomplete and the nested for loop solution will already have poor computational time.

That function merely tries to sort the transactions so that only the remaining balance remains, by subtracting an outgoing from the nearest incoming balance, and carrying that remainder to the next incoming balance

I feel like a recursive solution would be better, or maybe something more elegant that I hadn't thought of (nested Object forEach accessor in javascript)

After I get them sorted then I need to actually do the weighted average method, which I have some ideas for already.

First sorting, then weighted average of the remaining quantities.

Anyway, I know the javascript community on StackOverflow is particularly harsh about asking for help but I'm at an impasse because not only do I want a solution, but a computationally efficient solution, so I will probably throw a bounty on it.

You could convert the objects into an array of timestamp-value pairs. Outgoing ones could be negative. Then you can easily sort them after the timestamp and accumulate how you like it:

 const purchases = Object.entries(incomingArray).concat(Object.entries(outgoingArray).map(([ts, val]) => ([ts, -val])));

 purchases.sort(([ts1, ts2]) => ts1 - ts2);

Now you could iterate over the timespan and store the delta in a new array when the value increases (a new ingoing):

 const result = [];
 let delta = 0, lastIngoing = purchases[0][0];

 for(const [time, value] of purchases){
   if(value > 0){
    // Store the old
    result.push([lastIngoing, delta]);
    // Set up new
   delta = 0;
   lastIngoing = time;
  } else {
   delta += value;
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM