簡體   English   中英

比較兩個 arrays 的值並相應地創建對象

[英]Comparing values from two arrays and creating objects accordingly

第一次寫問題,所以我會盡量弄清楚問題是什么。

我有 2 個 arrays 填充了不同的值,我正在嘗試 map 來自第一個數組的值是值的輸入,到第二個是輸出。

如果第一個數組中的第一個 object 小於第二個數組中的數量,則就像第一個 object 將其所有值發送到第二個 object 一樣,每個 object 依此類推,直到滿足第二個 object 的值。

通過這種方式,我想從一個 object 到另一個 map 值,例如,如果第一個 object 中的值大於第二個 object,他將發送部分第一個對象值來滿足整個第二個 object 和然后部分還有下一個....這是 arrays 以及它應該如何結束的示例。

我還使用 BigNumber.js 和 formatUnit function 來整理數字。

const firstArray =[ 
    { value: 0.001, sender: "one"},
    { value: 0.01, sender: "two"},
    { value: 0.1, sender: "three"},
    { value: 3.0, sender: "four"},
    { value: 0.002, sender: "five"},
    { value: 0.0003, sender: "six"},
    { value: 5.0, sender: "seven"}
    ]
const secondArray = [ 
    { value: 0.5, recipient: "a"},
    { value: 3.5, recipient: "b"},
    { value: 4.2133, recipient: "c"}
    ]

我想做的是:

我想很好地 map 以便最終數組看起來如下所示:

const thirdArray = [
    {sender : one, receiver : a, amount : 0.001},
    {sender : two, receiver : a, amount : 0.01},
    {sender : three, receiver : a, amount : 0.1},
    {sender : four, receiver : a, amount : 0.389},
    {sender : four, receiver : b, amount : 2.611},
    {sender : five, receiver : b, amount : 0.002},
    {sender : six, receiver : b, amount : 0.0003},
    {sender : seven, receiver : b, amount : 0.8867},
    {sender : seven, receiver : c, amount : 4.2133}]

我想出的是:

    let i = 0;
    let j = 0;

    let thirdArray = [];

     while (i < firstArray.length) {
        let input = new BigNumber(firstArray[i].value);

        while (j < secondArray.length) {
          input = input.minus(new BigNumber(secondArray[j].value));

          // Format units for amount
          const formattedAmount = formatUnits(secondArray[j].value, -8);

          // Initialize responseObject
          const responseObj = {
            sender: firstArray[i].sender,
            receiver: secondArray[j].recipient,
           amount: formattedAmount,
          };

          if (input.isLessThan(0)) {
            let output = new BigNumber(secondArray[j].value);
            output = output.minus(input.times(-1));
            thirdArray.push({
              ...responseObj,
              amount: formatUnits(output.toNumber(), -8),
            });
            output = input.times(-1);
            break;
          }
          thirdArray.push(responseObj);
          j += 1;
          if (input.isEqualTo(0)) break;
        }
        i += 1;

      }
    console.log(thirdArray)

(暫時回復)

[
  { sender: 'one', receiver: 'a', amount: '0.001' },
  { sender: 'two', receiver: 'a', amount: '0.01' },
  { sender: 'three', receiver: 'a', amount: '0.1' },
  { sender: 'four', receiver: 'a', amount: '0.5' },
  { sender: 'four', receiver: 'b', amount: '2.5' },
  { sender: 'five', receiver: 'b', amount: '0.002' },
  { sender: 'six', receiver: 'b', amount: '0.0003' },
  { sender: 'seven', receiver: 'b', amount: '3.5' },
  { sender: 'seven', receiver: 'c', amount: '1.5' }
]

與我想要得到的相比:

[
  { sender : one, receiver : a, amount : 0.001 },
  { sender : two, receiver : a, amount : 0.01 },
  { sender : three, receiver : a, amount : 0.1 },
  { sender : four, receiver : a, amount : 0.389 },
  { sender : four, receiver : b, amount : 2.611 },
  { sender : five, receiver : b, amount : 0.002 },
  { sender : six, receiver : b, amount : 0.0003 },
  { sender : seven, receiver : b, amount : 0.8867 },
  { sender : seven, receiver : c, amount : 4.2133 }
]

任何幫助將非常感激!

我將問題解釋為...鑒於這些類型:

interface Sender {
  sender: string;
  value: number;
}   
interface Recipient {
  recipient: string;
  value: number;
}
interface Transaction extends Sender, Recipient { }

執行以下 function:

declare function getTransactionArray(
  senderArray: Sender[], 
  recipientArray: Recipient[]
): Transaction[];

senderArray中的發件人按順序向 recipientArray 中的recipientArray發送值,但是您保留當前發件人直到她發送所有此處的值,並且您保留當前收件人直到他收到她的所有值。


這是一種方法:

function getTransactionArray(senderArray: Sender[], recipientArray: Recipient[]
) {    
  const epsilon = 1e-10; // anything less than this is considered zero

  // copy arrays
  senderArray = senderArray.map(s => ({ ...s }));
  recipientArray = recipientArray.map(s => ({ ...s }));

  const transactionArray: Transaction[] = [];
  while (senderArray.length && recipientArray.length) {
    const sender = senderArray[0];
    const recipient = recipientArray[0];
    const value = Math.min(sender.value, recipient.value);
    sender.value -= value; // perform transaction
    recipient.value -= value; // perform transaction
    transactionArray.push({ // record transaction
      sender: sender.sender, 
      recipient: recipient.recipient, 
      value 
    });
    if (!(sender.value > epsilon)) senderArray.shift();
    if (!(recipient.value > epsilon)) recipientArray.shift();
  }
 
  if (senderArray.length) console.log("WARNING! No receipients for", senderArray);
  if (recipientArray.length) console.log("WARNING! No senders for ", recipientArray);
  return transactionArray;
}

這是一個命令式算法,我們復制senderArrayrecipientArray數據並對副本進行變異(與沒有 state 更改的純函數算法相反)。

這個想法是我們獲取第一個發送者和第一個接收者(如果沒有第一個發送者,或者如果沒有第一個接收者,那么我們就完成了)並確定要發送的值。 這是發送者想要發送的值和接收者想要接收的值中的最小值 然后我們通過從發送者和接收者中減去這個值來執行交易。 並且我們將交易記錄在 output 數組中。 最后,如果發送者發送了她所有的值,則發送者從數組中刪除,如果接收者收到了他的所有值,則從數組中刪除。

(請注意,我將剩余的值數量與epsilon進行了比較;我使用 JavaScript 的標准浮點算法進行計算,因此有時由於精度問題,您可能會得到一個發件人或收件人剩余微小的正值......之后all, 0.1 + 0.2 - 0.3 !== 0 。所以我選擇了一些epsilon ,我希望它比我們關心的任何實際數量都小。如果你使用不同的數字數據結構,那么你可能會改變這種比較的完成方式。)

最后,如果發件人留下一些未發送的值或收件人留下一些未收到的值,我們可能會在可能記錄警告之后返回交易數組......如果發件人值的總和不匹配,就會發生這種情況收件人值的總和。


讓我們測試一下:

const senderArray: Sender[] = [
  { value: 0.001, sender: "one" },
  { value: 0.01, sender: "two" },
  { value: 0.1, sender: "three" },
  { value: 3.0, sender: "four" },
  { value: 0.002, sender: "five" },
  { value: 0.0003, sender: "six" },
  { value: 5.0, sender: "seven" },
  { value: 0.1, sender: "eight" }
];

const recipientArray: Recipient[] = [
  { value: 0.5, recipient: "a" },
  { value: 3.5, recipient: "b" },
  { value: 4.2133, recipient: "c" }
];

我在其中添加了另一個發件人以使總和相等:

const transactionArray = getTransactionArray(senderArray, recipientArray);

console.log("[\n" + transactionArray.map(v =>
  JSON.stringify(({ ...v, value: v.value.toFixed(4) }))
).join(",\n") + "\n]");

/* [
{"sender":"one","recipient":"a","value":"0.0010"},
{"sender":"two","recipient":"a","value":"0.0100"},
{"sender":"three","recipient":"a","value":"0.1000"},
{"sender":"four","recipient":"a","value":"0.3890"},
{"sender":"four","recipient":"b","value":"2.6110"},
{"sender":"five","recipient":"b","value":"0.0020"},
{"sender":"six","recipient":"b","value":"0.0003"},
{"sender":"seven","recipient":"b","value":"0.8867"},
{"sender":"seven","recipient":"c","value":"4.1133"},
{"sender":"eight","recipient":"c","value":"0.1000"}
]*/

看起來不錯!

游樂場代碼鏈接

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM