2016-05-03 74 views
3

我有這種形式的數據(簡化,但承擔管理和礦業之間的20列):在D3的系列創建系列

Date,Series,Admin,Mining,CPI 
1990,Ordinary Time Earnings,20,30,96 
1991,Ordinary Time Earnings,22,33,100 
1990,Total Earnings,25,38,96 
1991,Total Earnings,29,43,100 

其中我分離成兩個系列這樣的:

d3.csv("avgearnings_v1_1.csv", function(error, data) { 
    if (error) throw error; 
    OrdinaryTimeEarnings = data 
    .filter(function(d) { 
     if(d.Series == 'Ordinary Time Earnings') 
      return d; 
    }); 
    TotalEarnings = data 
    .filter(function(d) { 
     if(d.Series == "Total Earnings") 
      return d; 
    }); 

並且可以在沒有任何問題的情況下顯示圖表。我接下來要做的是創建兩個系列:

OrdinaryTimeEarningsReal = OrdinaryTimeEarnings; 
TotalEarningsReal = TotalEarnings; 

然後重新計算這些新系列。基本上是:

  • 對於不日期/系列/ CPI
  • 由100
  • 就拿CPI值當年
  • 單獨由CPI將每個採礦,管理列的繁衍任何列
  • 所以:新值=(舊值]/[CPI])* 100

我的代碼是可怕的,但我可以利用這個得到正確的價值觀:

OrdinaryTimeEarningsReal 
    .forEach(function (z,i) { 
     var CPI = z["CPI"]; 
     d3.map(z, function(b) {return b;}) 
      .forEach(function (c) { 
       if(c !== "Date" && c !== "Series" && c !== "CPI") 
        OrdinaryTimeEarningsReal[i][c] = ((z[c])/(CPI))*100;  
      }); 
    }); 

但是,當我這樣做時,它也會以某種方式更新原始OrdinaryTimeEarnings系列,使它們彼此相等,並且OrdinaryTimeEarnings中的原始數據丟失。

我不確定這是否是我使用裸對象(在它內部迭代的過程中,eek!),或者上面的代碼實際上是在更改原始數據對象中的值(以及所有4個我之後創建的系列只是對它的引用)。

無論哪種方式,我無法解決它!我嘗試了一些公平的幾種不同的語法形式,但不能解決它。幫助將非常感激實現這一點。

回答

2

如果你確實使用此代碼「複製」你的陣列:

OrdinaryTimeEarningsReal = OrdinaryTimeEarnings; 
TotalEarningsReal = TotalEarnings; 

然後你提到它是正確的,當你說他們引用同一個對象時。在JavaScript中,數組是可變的,使用上面的代碼,您只需創建2個新變量,並引用內存中的現有數組。

爲了深克隆你的對象的數組,使用以下方法:

OrdinaryTimeEarningsReal = JSON.parse(JSON.stringify(OrdinaryTimeEarnings)); 
TotalEarningsReal = JSON.parse(JSON.stringify(TotalEarnings)); 

這將創建數組的副本,並將它們分配給新的變量,因此,當你編輯時,初始數組將保持不受影響。

現在,關於你的代碼,它有點太複雜。如果我理解正確什麼是你想實現的,你可以按如下簡化它:

OrdinaryTimeEarningsReal 
.forEach(function (z,i) { 
    for (var c in z) { 
     if (z.hasOwnProperty(c) && c !== "Date" && c !== "Series" && c !== "CPI") 
      z[c] = z[c]/z.CPI * 100;  
    }); 
}); 

祝你好運!

+0

我一直在爲此解決方案,並意識到我需要添加slice()。我已經添加了它,但原始數據似乎被覆蓋:https://jsfiddle.net/thatOneGuy/9ywLytjf/3/ – thatOneGuy

+0

@thatOneGuy哦,它發生是因爲.slice()仍然會將對象引用複製到新數組中。數組本身指向內存中的另一個對象,但組件對象仍然指向相同的位置。而不是'slice',使用'JSON.parse(JSON.stringify(data))'。這是你的小提琴的工作[fork](https://jsfiddle.net/dot07ggy/)。 – iulian

+0

@thatOneGuy我已經用深度克隆數據的新方法更新了我的答案。 – iulian

1

如果我理解正確:

data.forEach(function(d) { 
    for (var key in d) { 
    if (key !== 'Date' && key !== 'Series' && key !== 'CPI') { 
     d['new' + key] = (d[key]/d.CPI) * 100; 
    } 
    } 
}) 
console.log(data) 

我已經加入new到新的屬性,因此新adminnewAdmin

實現小提琴:https://jsfiddle.net/thatOneGuy/9ywLytjf/

+0

剛剛意識到你的問題,另一個答案是關於slice()是要走的路 – thatOneGuy