繁体   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