[英]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;
}
这是一个命令式算法,我们复制senderArray
和recipientArray
数据并对副本进行变异(与没有 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.