【问题标题】:retrieve object from array WHERE another object matches another array从数组中检索对象 WHERE 另一个对象匹配另一个数组
【发布时间】:2020-04-06 00:39:15
【问题描述】:

请注意:this is NOT 重复:涉及不同的需求。

我正在开发基于 Google 表格的加密资产组合。摘要页面提供任何交易所中所有资产的余额。

第一个函数连接到第一个交易所的账户(比如 Bitstamp),并下载你钱包中所有资产名称的最新列表,并将它们写在第一列,以及下面的相应余额交流专栏。

然后第二个函数从第二个交易所的账户(比如说币安)中检索资产的金额,并将它们写入相应的列,但是这次当然脚本需要将金额与已经写入的资产名称相匹配从第一个脚本开始。

这里没有固定单元格!!!

换句话说,第二个脚本需要了解设置了WHAT ROW,例如第一列中的BTC,并且需要在相应行的binance列中写入相应的btc数量..

如果我们在 sql 上,你可以写类似


set btc_amount FROM binance in BINANCE column WHERE btc_asset === cell(i+2, 1).getValue() 

不幸的是,这太容易了,所以我想我们做不到..

现在,你有什么建议?数组比较?数组数组数组?数组映射?数组过滤器? filter.this?

这是我迄今为止尝试过的:没有什么是 100% 有效的。有些东西根本不起作用。

...
  var data = UrlFetchApp.fetch(url, params);
  var data = JSON.parse(data.getContentText());
  var data = data.balances;

  //binance api returns also assets with zero balance, so we need to filter
  var data = data.filter(function (el) {
     return el.free > 0; 
});



  var i;
  for (i=0; i < data.length; i++) {

  var asset = data[i].asset;
  //this bizarre back and forth is needed in order to BOTH get rid of trailing zeros AND render the value a number format
  var free  = data[i].free;   var a = parseFloat(free);   var a = a.toString();    var free = parseFloat(a);

  //my first choice was to convert the list from the 1st column into an array and try to perform some sort of comparison or mapping  
  var cont  = sheet.getRange(2, 1, 16).getValues();
  //var cont  = cont.toLowerCase()

  //then flattening the array from 2d to 1d    
  function flatten(tdArray){
  return [].concat.apply([], tdArray);
}   
  var cont  = flatten(cont);

  var corr = sheet.getRange(i + 2, 1).getValue();

  var check = data.map(function (value){
    return value.asset == cont; 
  }); 



   if (check == true) {sheet.getRange(i + 2, 8).setValue(free)}


  //var check = check[i];

 // if (check == true){sheet.getRange(i + 2, 8).setValue(free);}  

    //sheet.getRange(i + 2, 1).setValue(asset);
    //sheet.getRange(i + 2, 8).setValue(free);
  }//fine del for

  Logger.log(corr);  
}
var data = UrlFetchApp.fetch(url, params);
  var data = JSON.parse(data.getContentText());
  var data = data.balances;

  var data = data.filter(function (el) {
     return el.free > 0; 
});



  var i;
  for (i=0; i < data.length; i++) {

  var asset = data[i].asset;
  var free  = data[i].free;   var a = parseFloat(free);   var a = a.toString();    var free = parseFloat(a);

  var cont  = sheet.getRange(2, 1, 16).getValues();
  //var cont  = cont.toLowerCase()

  function flatten(tdArray){
  return [].concat.apply([], tdArray);
}   
  var cont  = flatten(cont);

  var h;
    for (h=0; h<cont.length; h++){if (cont[h] === asset){sheet.getRange(i + 2, 8).setValue(free)}}




//  Logger.log(corr);  
  }}

这是迄今为止我一直在尝试的两个解决方案。谢谢

编辑:具有不同 Json 结构的新类似案例

我已将 ziganotschka 建议的相同模式应用于 Bitstamp 案例。

现在,正如您所看到的,Bitstamp 返回的 Json 响应与来自 binance 的响应不同,这使我更难检索对象和属性,因为它的行为和外观与 binance 不一样,即:作为一个典型的数组:

Bitstamp Json 数据

{btc_available=0.00000684, eth_reserved=0.00000000, eur_balance=0000.63, btcusd_fee=0.500, xrpeur_fee=0.500, btc_balance=0.00000684, xrp_withdrawal_fee=0.02000000, ethusd_fee=0.500, ltceur_fee=0.500, eth_balance=0.11033051, xrp_reserved=0.00000000, bchusd_fee=0.500, eur_reserved=0.00, bch_available=0.00000000, usd_available=0.18, xrp_available=0.75000000, xrpusd_fee=0.500, ltcbtc_fee=0.500, bcheur_fee=0.500, ltc_available=0.00000000, btc_reserved=0.00000000, ltc_withdrawal_fee=0.00100000, usd_reserved=0.00, btc_withdrawal_fee=0.00050000, eurusd_fee=0.500, xrp_balance=0.75000000, ltcusd_fee=0.500, ltc_balance=0.00000000, bch_reserved=0.00000000, bch_withdrawal_fee=0.00010000, eur_available=0000.63, ltc_reserved=0.00000000, bchbtc_fee=0.500, ethbtc_fee=0.500, etheur_fee=0.500, usd_balance=0.18, eth_available=0.11033051, btceur_fee=0.500, eth_withdrawal_fee=0.00100000, bch_balance=0.00000000, xrpbtc_fee=0.500}

币安Json数据

 {balances=[{asset=BTC, free=0.00966600, locked=0.00000000}, {asset=LTC, free=0.00000000, locked=0.00000000}, {asset=ETH, free=0.00001251, locked=0.00000000}, {asset=NEO, free=0.00000000, locked=0.00000000}, {asset=BNB, free=0.07496873, locked=0.00000000}, {asset=QTUM, free=0.00000000, locked=0.00000000}, {asset=EOS, free=0.00000000, locked=0.00000000}, {asset=SNT, free=0.00000000, locked=0.00000000}, {asset=BNT, free=0.00000000, locked=0.00000000}, {asset=GAS, free=0.00000000, locked=0.00000000}, ...

所以我最终构建了两个新数组,然后加入它们,从一开始就过滤数组:

var data = JSON.parse(data.getContentText());

var keys    = Object.keys(data);
var values  = Object.keys(data).map(function(e){return data[e]});

var result = [];
var k;
for (k=0; k<keys.length; k++){
  if (keys[k].slice(4, 13) == "available") {result.push([keys[k], values[k]]);}}

    var i;
  for (i=0; i<result.length; i++) {

  var key     = result[i][0].slice(0,3);
  var key     = key.toUpperCase();


  var row     = rows.indexOf(key)+2;
  var value   = result[i][1];

     if (row>=2){
       sheet.getRange(row, 5).setValue(value);

     }  
  }

它确实有效,但我确信有一种更优雅或更直接的方法可以做到这一点。我首先考虑将 Json 转换为一个数组,以使其看起来(和工作)像 binance 代码中的那个,但我做不到。有什么建议吗?

【问题讨论】:

  • 您的问题是关于如何将数据条目分配到正确的行(A 列中的条目等于data[i].free 的行?
  • 准确的说是A列的entry等于data[i].asset的那个,对应同一个json对象中的一个且唯一一个data[i].free。谢谢

标签: javascript arrays json google-apps-script google-sheets


【解决方案1】:

您可以使用indexOf()

此方法允许您查找字符串在数组中的位置。

基于您的数据的示例代码 sn-p:

function myFunction() {
...
  var oldAsset=sheet.getRange(2, 1, 16).getValues(); //Is the range fix or dynamic?
  var rows=[];
  for (j=0; j < oldAsset.length; j++) {
    rows.push(oldAsset[j][0]);
  }
  var data=...//here comes your data processing part
  for (i=0; i < data.length; i++) {
    var newAsset=data[i].asset;
    var free  = data[i].free;  // process as necessary
    var row=rows.indexOf(newAsset)+2; //THIS THE CRUCIAL PART TO FIND THE CORRECT ROW
     if (row>0){
       sheet.getRange(row, 8).setValue(free);
    }   
  }
}

我没有在这段代码中实现 sn-p 处理步骤,例如 toLowerCase(), parseFloat() 等等,因为我不知道你的 数据看起来像。

【讨论】:

  • 谢谢!!为什么我没有想到:找到位置..我会立即尝试并尽快回复您,谢谢
  • 谢谢,它有效!唯一的事情:我猜你的意思是var row=rows.indexOf(newAsset)+2; 。非常感谢,我自己无法制作它。我会预留一些时间来研究它,如果你愿意的话,我会要求进一步的解释。谢谢
  • 是的,indexOf(newAsset)!很高兴它对您有所帮助!
  • 我现在能想到的将数据转换为 JSON 对象的最简单方法可能是正则表达式。例如。 data=data.replace(/=/g,":"); 和类似的东西插入引号。
  • 谢谢,但我完全切换到 coinmarketcap api,而不是 coingecko:它提供了更常见的数组结构,因此暂时不再需要转换为 json。还是谢谢
猜你喜欢
  • 1970-01-01
  • 2020-02-21
  • 2019-04-14
  • 2021-03-30
  • 2021-05-14
  • 2022-11-14
  • 2020-06-08
  • 2019-07-04
  • 1970-01-01
相关资源
最近更新 更多