2011-03-09 18 views
1

我的一項新任務需要我將數據從一種格式轉換或映射到另一種格式,通常是從xcel,csv或ms mdb轉換爲xml,sql或根據我給出的規範所以通常每個映射都是不同的。我已經開始學習Python,將其作爲Lisp的先驅。我每天都在學習更多東西,而且我的工作確實很有趣。我正在試圖將我的大腦包裹在發電機和迭代器周圍,但我還不確定何時需要它們,但這裏是我卡住的地方。使用Python劃分列表以映射數據的問題

什麼是適當的pythonic方式來使用切片內的值來測試某些條件,如果符合然後分配適當的值。當我嘗試一個if elif與< =我沒有得到我想要的結果。下面的例子只是我創建的用於測試條件的許多if語句中的一個。

#This works 
hsa_id = '' 
if "1" in csvitem[63:64]: 
    hsa_id = '<4 hours' 
elif "2" in csvitem[63:64]: 
    hsa_id = '<4 hours' 
elif "4" in csvitem[63:64]: 
    hsa_id = '4-8 hours' 
elif "5" in csvitem[63:64]: 
    hsa_id = '4-8 hours' 
elif "6" in csvitem[63:64]: 
    hsa_id = '4-8 hours' 
elif "8" in csvitem[63:64]: 
    hsa_id = '8-16 hours' 
elif "9" in csvitem[63:64]: 
    hsa_id = '8-16 hours' 
elif "16" in csvitem[63:64]: 
    hsa_id = '16-24 hours' 
elif "17" in csvitem[63:64]: 
    hsa_id = '16-24 hours' 
elif "24" in csvitem[63:64]: 
    hsa_id = '16-24 hours' 
elif "25" in csvitem[63:64]: 
    hsa_id = '>24 hours' 
else: 
    hsa_id = '' 
HOURSSINCEAWAKENING.append(hsa_id) 

#This does not work. I tried removing the quotes. With and without the quotes I get all identical values. 
hsa_id = '' 
    if csvitem[63:64] <= "3": 
     hsa_id = '<4 hours' 
    elif csvitem[63:64] <= "7": 
     hsa_id = '4-8 hours' 
    elif csvitem[63:64] <= "15": 
     hsa_id = '8-16 hours' 
    elif csvitem[63:64] <= "23": 
     hsa_id = '16-24 hours' 
    elif csvitem[63:64] > "23": 
     hsa_id = '>24 hours' 
    else: 
     hsa_id = '' 
    HOURSSINCEAWAKENING.append(hsa_id) 

#Output from what does not work truncated for brevity as there are thousands of records. 
['<4 hours', '<4 hours', '<4 hours', '<4 hours',... 

回答

1

您正在比較字符串,可能您想比較數字。使用int()

if int(csvitem[63]) <= 3: 

也許你也想重構你的代碼,以消除這麼多if。作爲一個例子,你可以做這樣的事情:

data = [(3, '<4'), (7, '4-8'), (15, '8-16'), (23, '16-24'), (10000, '>24'] 

dattime = int(cvsitem[63]) 
hsa_id = '' 
for mytime, text in data: 
    if dattime <= mytime: 
     hsa_id = '%s hours' % text 
     break 

而且你的代碼中的第一鏈if也可以做同樣的事情。然而,在這種情況下,最好用你的選項建立一個字典,然後將其用作:

choices_dict = {'1':'<4 hours', ...} 
hsa_id = choices_dict.get(cvsitem[63], '') 
+0

我最初嘗試過,但由於該片是一個列表,我無法將該項轉換爲測試的整數。我得到以下錯誤:if int(csvitem [63:64])<= 3: TypeError:int()參數必須是字符串或數字,而不是'list' – MWR 2011-03-09 20:18:48

+0

列表中只有一個字符,嘗試int cvsitem [63:64] [0]) – joaquin 2011-03-09 20:21:25

+0

在任何情況下,您都可以使用cvsitem [63]進行簡化,您將直接得到數字而不是帶有數字的列表。 – joaquin 2011-03-09 20:30:27

0

問題:

  • 你的片包含單個字符,但你比較2.
  • 你正在做相關的字符串比較,而不是整數比較。
  • Python有一個處理CSV數據的模塊,所以你根本不需要切片。
  • 你應該使用一個字典來保存你想比較的值,而不是有一個大的if/elif結構。
+0

我不明白我在比較2的位置?我想說,如果csvitem [63:64] <=「3」:那麼做點什麼。我基本上希望python採取slice csvitem [63:64]上的任何值,並將其與一個值進行比較,如果爲true,則將該變量設置爲期望的值。在這種情況下,我沒有使用字典,因爲我必須維護順序,我使用Python 2.6,據我所知它沒有像py3.1 +那樣的有序字典。 – MWR 2011-03-09 20:25:11

+0

'elif csvitem [63:64] <=「23」:'將1與2進行比較。您將使用該詞典來存儲比較值,而不是結果。 – 2011-03-09 20:26:51

1

您正在比較字符串。看看那些比較:

>>> "23"<"3" 
True 
>>> "04"<"3" 
True 

我想你想比較整數值。試試這個: ... 如果INT(csvitem [63:64])< = 3: ... 等

0

到底是什麼csvitem在你的榜樣?從你的例子(和名字)中,我假設它是一些某種項目的序列。例如[「a」,「b」,「c」....「25」,...]。

但是,在這種情況下,採取切片並使用in有點迂迴 - 它提取單個元素的列表(例如[「25」]和檢查成員資格),而應該像`if '25'== csvitem [63]。

您的其他問題是因爲該項目的數據類型是一個字符串,它將與數字進行不同的比較。該int的功能,例如:

if int(csvitem[63]) <= 3: 
    hsa_id = '<4 hours' 

而且,它可能是這裏值得注意的蟒蛇的一個有用的功能:即OPER的ator連鎖。與許多語言不同,您可以使用語法「lowerbound < value < upper_bound」(使用適當的比較)檢查一系列值。你可以寫你的例子:

hours = int(csvitem[63]) 
if hours < 4: 
    hsa_id = "<4 hours" 
elif 4 <= hours < 8: 
    hsa_id = "4-8 hours" 
elif 8 <= hours < 16: 
    hsa_id = "8-16 hours" 
elif 16 <= hours <= 24: 
    hsa_id = "16-24 hours" 
else: 
    hsa_id = ">24 hours" 
+0

你是完全正確的,我從每個數千條記錄中取出一個條目,並基於某種條件,我希望將舊值映射到或轉換爲新值。在這種情況下,我在每條記錄中都有一個表示清醒小時數的字段,我想測試該值並將其映射到新條件。因此,對於所有值爲0到3的記錄,我希望所有這些值都變爲「<4小時」。我知道鏈接,但我一直無法弄清楚如何將分片項目轉換爲int,因爲如果這有意義,則列表中的每個項目都是子列表。 – MWR 2011-03-09 20:42:42

+0

問題是,一個列表的切片總是一個列表。當你提取單個元素時,根本不要使用切片,直接使用索引(即csvitem [63]而不是csvitem [63:64])。或者,如果你已經有了這個切片,用Slice [0] – Brian 2011-03-10 12:13:41

1

當你告訴python比較事情時,它很少會抱怨。如果你告訴它比較一串香蕉,它可能會告訴你一個比另一個大,但答案對你沒有意義。

您正在比較字符串與數字。您應該將數字與數字進行比較:

>>> "3" < "20" 
False 
>>> "3" < "20" 
False 
>>> int("3") < int("20") 
True 

比較之前將您的字符串轉換爲數字,您會沒事的。

+0

獲得第一個(單個)元素,那麼當我在讀取csv後創建我的列表時,我可以這樣做嗎?我正在閱讀我的csv文件,其中包括:'try: rlist = list(csv.reader(rh))' 'csv.Error除外:' 'sys.exit(「file%s,line%d:% s)%(filename,reader.line_num,e))' 'finally:' 'rh.close()'然後我用下列枚舉列表:'mList = enumerate(rlist)' ' csvitem in mList:'然後從這裏我測試包含需要轉換或映射到新含義的數據的片。 – MWR 2011-03-09 20:49:30

+0

@MWR我認爲最好的方法是創建一個反映csv中行內容的類。在__init__方法中,將需要的切片,必要時轉換爲整數(或其他),然後(如果需要)爲對象的成員提供訪問器屬性。這會將CSV格式與程序的其餘部分分離,因爲您將處理自己的對象,並且如果格式發生更改,或者數據通過不同的界面到達,則其他邏輯將保持不變。它也會執行你需要的類型轉換,當然 – slezica 2011-03-09 21:06:14