我正在尝试获取总买入和卖出的阵列。但是,看起来很难找到方法。
我遍历数组,但是无法以名称显示买卖的总和。
const orders = [
['AAPL', 'buy', 100],
['GOOG', 'sell', 10],
['AAPL', 'buy', 100],
['AAPL', 'sell', 100],
['AAPL', 'sell', 20],
];
function transform(orders) {
const result = {};
orders.forEach(element => {
})
return result;
}
<div id="result"></div>
我想要输出:
/*
result = {
// total_buy, total_sell
'AAPL': [ 200, 120 ],
'GOOG': [ 0, 10]
}
*/
任何帮助将不胜感激。
答案 0 :(得分:5)
使用Array.reduce
并检查第二个条目(操作)以将金额添加到正确的位置:
const orders = [
["AAPL", "buy", 100],
["GOOG", "sell", 10],
["AAPL", "buy", 100],
["AAPL", "sell", 100],
["AAPL", "sell", 20]
];
const result = orders.reduce((acc, [key, action, amount]) => {
acc[key] = acc[key] || [0, 0];
if (action === "buy") acc[key][0] += amount;
if (action === "sell") acc[key][1] += amount;
return acc;
}, {});
console.log(result);
答案 1 :(得分:3)
您可以将对象作为结果以及获取正确索引的类型。
function transform(orders) {
return orders.reduce((result, [key, type, value]) => {
result[key] = result[key] || [0, 0];
result[key][{ buy: 0, sell: 1 }[type]] += value;
return result;
}, {});
}
const orders = [['AAPL', 'buy', 100], ['GOOG', 'sell', 10], ['AAPL', 'buy', 100], ['AAPL', 'sell', 100], ['AAPL', 'sell', 20]];
console.log(transform(orders));
.as-console-wrapper { max-height: 100% !important; top: 0; }
答案 2 :(得分:1)
这是您可以做到的一种方法:
const orders = [
['AAPL', 'buy', 100],
['GOOG', 'sell', 10],
['AAPL', 'buy', 100],
['AAPL', 'sell', 100],
['AAPL', 'sell', 20],
];
const result = {};
orders.map((order) => {
const [ tag, type, amt ] = order;
if (!result[tag]) result[tag] = [0, 0];
if (type == "buy") result[tag] = [result[tag][0] + amt, result[tag][1]];
if (type == "sell") result[tag] = [result[tag][0], result[tag][1] + amt];
});
console.log(result);
答案 3 :(得分:1)
由于其他所有人都在使用函数式编程,因此这是循环的一种旧方法:)
const orders = [
['AAPL', 'buy', 100],
['GOOG', 'sell', 10],
['AAPL', 'buy', 100],
['AAPL', 'sell', 100],
['AAPL', 'sell', 20]
];
function transform(orders) {
const result = {};
for (let i = 0; i < orders.length; i++) {
const [key, op, val] = orders[i];
if (!result[key]) { result[key] = [0, 0]; }
result[key][op === 'buy' ? 0 : 1] += val;
}
return result;
}
console.log(transform(orders));
答案 4 :(得分:1)
const transform = () => {
const orders = [
['AAPL', 'buy', 100],
['GOOG', 'sell', 10],
['AAPL', 'buy', 100],
['AAPL', 'sell', 100],
['AAPL', 'sell', 20],
];
return orders.reduce((acc, order) => {
const isBuyOption = order[1] === 'buy';
if (Array.isArray(acc[order[0]])) {
acc[order[0]][0] = acc[order[0]][0] + (isBuyOption ? order[2] : 0)
acc[order[0]][1] = acc[order[0]][1] + (!isBuyOption ? order[2] : 0)
} else {
acc[order[0]] = [
isBuyOption ? order[2] : 0,
!isBuyOption ? order[2] : 0
];
}
return acc;
}, {});
}
const result = transform();
console.log(result)
答案 5 :(得分:1)
我认为我会做得更深入,因此您将拥有思想过程,而不仅仅是最终代码。 (此外,我还是个混蛋,喜欢写作。:D)
在查看数据本身之前,首先要考虑的就是查看数据的用途。
首先,您要遍历数组以对其中的每个项目进行一些处理。这建议使用数组中内置的功能之一,例如forEach
或map
或reduce
。这些全部遍历数组的元素,将每个元素传递给您定义的函数。但是他们对这些数据做不同的事情。
forEach
使您可以访问每个元素,但并不希望您输出任何内容,仅出于某种原因使用信息即可。 (您可以更改某些内容,但最好不要使用旧数据并创建新版本,这样一来,您始终知道自己拥有一组新的数据,而不是直接进行调整。这是一个好主意。如果需要调整数据,请使用map
,如下所述。)map
使您可以访问每个元素,但希望您返回一些内容,以便根据从旧数组中获得的内容创建一个新数组。因此,如果您有一个数字数组,并且想要一个将这些数字转换为字符串的其他数组,则可以创建一个类似(number) => '' + number
的函数,将其传递给map
,然后您就可以最终会得到一个新数组,其中所有数字都转换为字符串。reduce
使您可以访问每个元素,但无需创建新的数组,而是可以组合信息,将其简化简化为某种形式的单个值或对象。这是我们将要使用的方法,因为我们要获取数组中的元素并将其插入到组合了信息的单个对象中。我们也可以使用for
循环来执行此操作,但是通过使用内置函数,我们可以专注于对我们很重要的工作-组合信息-然后数组执行遍历每个项目的内务处理工作。当我们将所有内容都放在下面时,这将变得更加清晰。
下一步是了解如何转换数据。一旦有了这些,就可以弄清楚如何将条目添加在一起。
如果您查看自己的交易,则每笔交易如下:
[name, buy or sell, amount]
最后想要的是一个对象,其键和值看起来像
name: [buy amount, sell amount]
一旦您看到了,关键就是弄清楚如何从一种安排转到另一种安排。
处理名称非常简单。您只需将其从数组传递给对象,而无需对其进行转换:
const name = transaction[0];
接下来要考虑的是如何将买入和卖出金额划分为单独的字段。如果买入应该在索引0处,卖出应该在索引1处,则可能很简单:
const amountIndex = transaction[1] === 'buy' ? 0 : 1;
最后一项是实际金额:
const amountValue = transaction[2];
然后,忽略如何将它们添加在一起,如果我们有一个resultsObject
可以将其插入,我们最终会得到
const name = transaction[0];
const amountIndex = transaction[1] === 'buy' ? 0 : 1;
const amountValue = transaction[2];
// create a new array with starting values
resultsObject[name] = [0, 0];
// put the transaction's value in the right place
resultsObject[name][amountIndex] = amountValue;
在第2步中有一些我们未解决的问题
这实际上很简单,但是值得一试,因为如果没有它,我们的结果将被完全弄乱。
第一个问题通过将上面的创建行替换为:
// create a new array with starting values (if it doesn't already exist)
if (! resultsObject[name]) {
resultsObject[name] = [0, 0];
}
通过在下一行中执行加法和赋值来回答第二个问题:
// add the transaction's value to the right place
resultsObject[name][amountIndex] += amountValue; // added the + sign
如果我们将它们放在一起,我们将获得如何将数组简化为对象的基本方法:
const name = transaction[0];
const amountIndex = transaction[1] === 'buy' ? 0 : 1;
const amountValue = transaction[2];
// create a new array with starting values (if it doesn't already exist)
if (! resultsObject[name]) {
resultsObject[name] = [0, 0];
}
// add the transaction's value to the right place
resultsObject[name][amountIndex] += amountValue; // added the + sign
reduce()
的函数我们几乎拥有完整的 reducer功能。我们只需要添加函数定义并返回值:
const getTransactionSummary = (resultsObject, transaction) => {
const name = transaction[0];
const amountIndex = transaction[1] === 'buy' ? 0 : 1;
const amountValue = transaction[2];
// create a new array with starting values (if it doesn't already exist)
if (! resultsObject[name]) {
resultsObject[name] = [0, 0];
}
// add the transaction's value to the right place
resultsObject[name][amountIndex] += amountValue; // added the + sign
return resultsObject;
}
该函数获取我们要收集的值( accumulator )和数组中的当前元素,并返回更新的累加器。
在reduce
中使用的任何功能都有两点要记住:
reduce
获得有效交易摘要的最后一步:
const getTransactionSummary = (resultsObject, transaction) => {
const name = transaction[0];
const amountIndex = transaction[1] === 'buy' ? 0 : 1;
const amountValue = transaction[2];
if (! resultsObject[name]) {
resultsObject[name] = [0, 0];
}
resultsObject[name][amountIndex] += amountValue;
return resultsObject;
}
const transactionSummary = transactions.reduce(getTransactionSummary, {});
(我删除了注释以对其进行清理。代码本身非常不言自明,并且注释破坏了最终产品中的流程。)
就是这样。最后一行采用您的数组(此处命名为transactions
)并调用其reduce
函数。我们给它提供减速器的参考,以及一个初次插入作为resultsObject的初始值。它返回完全填充的resultObject,并以我们想要的方式组合事务。 (如果我们不包含{}
作为初始值,则当浏览器抱怨您未定义累加器时,我们将收到另一个TypeError。)
将其与for
循环进行比较时,需要注意三件事:
这是声明性的。不必阅读循环和汇总数据的所有机制,而只需了解从左到右的内容即可: / p>
transactionSummary
的变量transactions
数组reduce
该数组... getTransactionSummary
通过在函数中定义代码,并将该函数作为参数进行归约,我们几乎可以从代码中创建一个句子。这可以帮助我们提高可读性。 除了使单行简明扼要之外,它还简化了我们的功能。该功能从顶部开始,在一种情况下直接向下工作。我们需要检查的条件越少,我们需要跟踪的循环越少,就越容易跟踪正在发生的事情。
getTransactionSummary
对于减少交易量很有用。如果我们要计算购买和出售的总数以获得总交易量,则可以创建一个不同的函数,例如getTransactionVolume
。只要使用一个累加器和一个数组元素,并返回更新的累加器,我们就可以用getTransactionSummary
替换getTransactionVolume
并从同一数据中获得完全不同的统计信息。这三个元素(尤其是第二个和第三个元素)使函数式编程如此漂亮。关于功能编程及其在JavaScript中的工作方式的文章很多。玩得开心!
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
答案 6 :(得分:0)
您是否正在寻找类似的东西?不过,这可能不是一个很好的解决方案。
const orders = [
['AAPL', 'buy', 100],
['GOOG', 'sell', 10],
['AAPL', 'buy', 100],
['AAPL', 'sell', 100],
['AAPL', 'sell', 20],
];
function transform(orders) {
const result = {};
orders.forEach(([transaction, type, amount]) => {
if (!result[transaction]) {
result[transaction] = [0, 0];
}
result[transaction][type === 'buy' ? 0 : 1] += amount;
})
return result;
}
let result = transform(orders);
console.log(result);
答案 7 :(得分:0)
这是您需要的吗?
const orders = [
['AAPL', 'buy', 100],
['GOOG', 'sell', 10],
['AAPL', 'buy', 100],
['AAPL', 'sell', 100],
['AAPL', 'sell', 20],
];
function transform(orders) {
var totalBuy = 0, totalSell = 0;
orders.map(order => {
if (order[1] == 'buy')
totalBuy += order[2];
else if (order[1] == 'sell')
totalSell += order[2];
})
console.log({totalBuy, totalSell})
}
transform(orders);
答案 8 :(得分:0)
尝试一下:
const data = {};
orders.forEach(innerArray => {
const [product, action, price] = innerArray;
data[product] = data[product] || [0, 0]
data[product][action === 'buy' ? 0 : 1] += +price
return data
})
答案 9 :(得分:0)
很多不错的选择。这是另一种策略-将其包装在函数中,并根据需要返回results
对象。
let results = {};
orders.forEach(order => {
if(!results[order[0]]) results[order[0]] = [0, 0];
order[1] === 'buy' ? results[order[0]][0] += order[2] :
results[order[0]][1] += order[2]
});