陣列的複製

  • Python的陣列跟java類似,直接用「=」只是復製了位置(call by reference)
  • 若要進行複製要使用copy()的函數
  • Python的陣列跟javaArrayList一樣,可以放入不同型態的資料

listone = [{'a':"oneData" , "two":"twoData"} , 1 ,2 ,3 , “abc”]

  • 上圖的例子,在陣列裡有字典的資料[0]integer[1,2,3],string[4]
  • 若直接用 listtwo = listone 只複製了參考,即兩個陣列的資料是共用的(記憶體位置相同)
  • pythoncopy()分成淺度跟深度兩種
  • 淺度copy
    • 使用copy()[:]的語法

listtwo = listone.copy()
listtwo = listone[:]

  • 此種做法,對於一般的intstring就會把值copy一份出來,但字典({'a':"oneData" , "two":"twoData"})仍是只複製參考
  • 深度copy
    • import copy,使用copy的函式 deepcopy

import copy;
copy.deepcopy(listone)

  • 此種做法,連字典({'a':"oneData" , "two":"twoData"})都會複製一份出來

陣列的排序

  • Python在陣列資料的sort上已經提供了基本的sortsorted函式,包含一般的數值、字串的排序
  • 然而,在字串的排序上,它是使用ASCII碼,意即會有大小寫的問題

listone = ["abc" , "btest" , "Btest", "ctest"]
兩種方法皆有相同結果
1. listone.sort()
2. sorted(listone);

//其它應用(直接輸入數值)
sorted((5,9,1,3))

  • 上述陣列經過sort前後的結果如下

  • 若要無關大小寫進行排序,sorted()函式有提供此作法,只要傳入參數「key=str.lower」即可

listone = sorted(listone, str.lower)

  • sorter的第二個參數 key=」還有很多用法,可在參照網路資料謝謝 :D

亂數(Random)

  • Random函數提供相當多的用法,例如隨機亂數、隨機浮點數、隨機選擇字元()、洗牌等功能
  • 需要import random
  • 隨機亂數 (可額外加上print印出結果)
    • 隨機挑選0~100的偶數

random.randrange(0,100,2)
>>>48

  • 隨機浮點數
    • 隨機產生0~10的浮點數

random. uniform (0,10)
>>9.148038516794944

  • 隨機選擇字元()
    • 可從一個串列中隨機選擇一個結果

random.choice("abcdefg")
>>>b
listone = ["abc" , "btest" , "Btest", "ctest"]
random.choice(listone)
>>>abc

  • 隨機選擇並重組
    • 從一個串列中選擇指定數量的內容,並重新組成新串列

listone = ["abc" , "btest" , "Btest", "ctest"]
random.sample(listone,2)
>>>["btest" ,"ctest"]

  • 亂數重組陣列內容(洗牌)
    • 將串列所有的內容重新排序

listone = ["abc" , "btest" , "Btest", "ctest"]
random.shuffle(listone)
>>>[" Btest " , " abc " , "btest", "ctest"]

定義新的資料結構

  • 對於資料結構當中,python都已經提供許多好用的結構(ex:字典key-value、陣列等)
  • 若這些結構已經符合您的需求,不應在額外自行建立新的資料結構(違反了python快速開發的精神)
  • 若對一些特別的需求,在使用上較不方便(例如堆疊Stack),可依目前的資料結構產生一個簡單的堆疊class(類似在java中用ArrayList做出堆疊的功能)

  • 如此可以增加程式可讀性,也可使用內建的資料結構
  • 以上僅僅是舉例,因為在新版的python中,list就有提供pop的功能,直接使用appendpop就能做到堆疊的資料結構

存取檔案的方法

  • 通常使用open(filename, mode)來開啟檔案
    • mode代表要用何種模式開啟檔案,r(唯讀)w(可寫入)a(要在檔案尾加東西)r+(可讀可寫)defaultr
    • windows的系統上,mode多了b(二元檔),表示要以二元模式(binary mode)開啟檔案
    • 文字檔的終止字元(end of line)在檔案讀寫時會被修改,對於一般的ASCII文字檔沒有影響,但若是像JPEG*.exe之類的二元檔就會產生問題
  • 讀寫檔案的方式

f = open("testnote.txt","r")

  • read(int)          輸入參數為要讀取的字元數,若不輸入數值,會將檔案所有內容轉換成string出來,要小心檔案內容過大的問題
  • readline()                則是將檔案內容一行行的讀取出來
  • write(string)   是將string寫入到檔案的最後面
  • 存取檔案就像是一個指標在file裡遊走,目前指標的位置在那,之後進行的操作(writeread)都會在此處進行
    • tell()                        可以得知目前指標位在file何處
    • seek(int)          可以改變目前指標的位置
  • 記得使用完檔案後,需呼叫close()來關閉檔案

存取檔案的方法 Part 2

  • python的檔案處理,有三個sys.stdinsys.stdoutsys.stderr,分別代表標準輸入、輸出與錯誤
  • 印出檔案內容前3行與後3

  • 計算單詞”python”在文件的出現次數

content = f.read()

print (content.count("python"))

  • 透過sys.argv取得傳入的參數,藉此來得到要處理的檔案名稱

inputFileName = sys.argv
print (inputFileName)

  • 由上述程式可得到傳入參數的陣列,可藉此得到要處理的文件名稱(切記,傳入的參數index1開始,0是執行的python *.py檔名)

存取檔案的方法 (fileinput)

  • fileinput可更簡單的進行檔案的操作,它可以尋訪檔案所有的內容,不同點在於他不是將所有內容讀取成list,而是產生了readlines的物件
  • 常用的函式如下
    • fileinput.input(path) ,找到可存取的檔案對象,若沒有輸入參數,會從輸入的參數中找資料
    • fileinput .filename(),印出檔案的名稱
    • fileinput .lineno(),印出目前指標所在的行數
    • fileinput .file lineno (),印出檔案所有的行數
    • fileinput .isfirstline(),判斷指標是否在第一行

  • 若沒有在input()輸入參數,會去抓執行python所輸入的參數(下述程式,會執行testnote.txttestnote_2.txt兩個檔案)

C:\> Python fileProcessing.pytestnote.txttestnote_2.txt

資料夾與檔案的處理

  • 若程式需要讀取一資料夾下所有的檔案,可用以下程式處理

  • os.listdir(str) 會回傳指定路徑下所有的檔案
  • os.curdir 是一個參數,會回傳當下的路徑
  • 上述程式用兩種方式呼叫

Glob(用於匹配多個檔案)

  • 採用上述的方法,只能輸入特定的檔案,若要匹配多個檔案(ex*.txt),便無法達成
  • 透過glob,便可以尋找大量相似的資料

  • 上述程式除了使用glob之外,還用到三個重要的概念,reducemapfilter

reduce

  • 可以重覆進行函式呼叫的操作,其函式定義如下

reduce(func_handler, value_list, init_value)

  • func_handler :要重覆呼叫的function (像是指標函式的概念,把函式傳進去)
  • value_list :要處理的list資料
  • init_value        :初始值
    • 如上所述,reduce會依序取出list前兩個參數,並執行函式的動作,並回傳一新的結果,再與下一個值繼續處理。
    • 例:現在有一個陣列有1~10的值,要求出陣列內值的總合

  • 最基本的做法,就是用for迴圈將值全部讀取出來,並用一變數加其總合
  • 而採用reduce,可以把加總這個重覆的動作寫成函式,來處理上述的動作

  • 處理流程:
    1. 會依序取出list前兩個參數 => sum(0,1)
    2. 回傳得到新結果=> sum(0,1) = 1
    3. 再與下一個值繼續處理 => sum(1, 2) 1是前一次的結果
  • 例:現在有一組資料[(1,”a”,3),(2,”b”,6),(3,”c”,9),(4,”d”,12)],我們要將資料處理並得到(1+2+3+4, ”abcd”, 3*6*9*12)結果,程式可寫成如下

  • 處理流程:
    1. 會依序取出list前兩個參數 => sum( (1,”a”,3) , (2,”b”,6) )
    2. 回傳得到新結果=> sum( (1,”a”,3) , (2,”b”,6) ) = (3,”ab”,18)
    3. 再與下一個值繼續處理 => sum((3,”ab”,18), (3,”c”,9))(3,”ab”,18),是前一次的結果
  • 因此,若看到程式需要重覆呼叫某個函式來計算結果的話,可以改用reduce來簡化程式碼

map

  • reduce差別在於,每一次的結果獨立,會回傳一個list(要用list(…)轉回來)

map(func_handler, value_list)
func_handler :要重覆呼叫的function (像是指標函式的概念,把函式傳進去)
value_list       :要處理的list資料(可傳多個list)

  • Reduce傳進去的function之所以有兩個參數,是因為會把上一次結果和下一個值做處理
  • map本身結果都是獨立的,因此參數僅需一個(也可一個以上,那map就必需多傳一個list進去才有辦法處理)
  • 例:現在有二組資料[(1,3),(2,6),(3,9),(4,12)][1,10,100,1000],我們要將資料處理讓兩組對應的資料相加與相乘的結果[(1+1,1*1), (2+10, 2*10) , (3+100, 3*100) , (4+1000, 4*1000)]

  • map(...)處理完的結果,記得要用list(…)將結果轉回list的格式

filter

  • 會將list的所有參數丟進function裡判斷,並回傳符合條件的結果,並組成list

map(func_handler, value_list…)
func_handler :要重覆呼叫的function (需要回傳booleanfunction)
value_list       :要處理的list資料(可傳多個list)

  • 例:現在有一個陣列有1~10的值,要找出有大於5的值並傳回list

  • 回到一開始的程式,見下面程式結果

  • 傳進reduceoperator.add 其實只是python預先定義好的加總函式,其動作如下

  • glob.glob的目的,就是依輸入的內容,找出符合其條件的所以檔案名稱,因此輸入的參數為「*.txt」,則glob.glob就會依此條件找出所有的txt檔案
  • 因此上述的程式流程
    • 經由map(glob.glob, sys.argv)將輸入的參數依續值行glob.glob函式,找出符合的檔案名稱
    • 在經由reduce(operator.add , map(…))map的結果轉回list
    • 此行程式改用list(map(…))也有相同結果

進階檔案處理

  • 將檔案內容拆成key-value
    • 假設原始檔案內容如下,要將它拆開成一個key-valuelist

  • 程式碼如下,透過stringsplit功能,透過關鍵字「,」將一行字串拆成兩部份

 

文章標籤
全站熱搜
創作者介紹
創作者 y23462001 的頭像
y23462001

y23462001的部落格

y23462001 發表在 痞客邦 留言(0) 人氣(1,747)