ලැයිස්තු අවබෝධය එදිරිව ලැම්බඩා + පෙරණය


887

මට මූලික පෙරීමේ අවශ්‍යතාවයක් ඇති බව මට පෙනී ගියේය: මට ලැයිස්තුවක් ඇති අතර අයිතමවල ගුණාංගයකින් එය පෙරීමට මට සිදුවේ.

මගේ කේතය මේ වගේ විය:

my_list = [x for x in my_list if x.attribute == value]

ඒත් එක්කම මම හිතුවා, මේ වගේ ලිවීම හොඳ නැද්ද?

my_list = filter(lambda x: x.attribute == value, my_list)

එය වඩාත් කියවිය හැකි අතර, කාර්ය සාධනය සඳහා අවශ්‍ය නම් යමක් ලබා ගැනීම සඳහා ලැම්බඩා පිටතට ගෙන යා හැකිය.

ප්‍රශ්නය: දෙවන ක්‍රමය භාවිතා කිරීමේදී යම්කිසි අවවාද තිබේද? කාර්ය සාධන වෙනසක් තිබේද? මට පයිතොනික් මාර්ගය මුළුමනින්ම මග හැරී ඇති අතර එය වෙනත් ආකාරයකින් කළ යුතුද (ලැම්බඩා වෙනුවට අයිතමය භාවිතා කිරීම වැනි)?


23
මීට වඩා හොඳ උදාහරණයක් වනුයේ ඔබේ පුරෝකථනය ලෙස භාවිතා කිරීම සඳහා දැනටමත් හොඳ නමක් ඇති ශ්‍රිතයක් තිබීමයි. එවැනි අවස්ථාවකදී, filterඑය කියවිය හැකි යැයි බොහෝ අය එකඟ වනු ඇතැයි මම සිතමි . ඔබට ලැයිස්තුවක් තුළ ඇති ආකාරයට භාවිතා කළ හැකි සරල ප්‍රකාශනයක් ඇති නමුත් එය පසුකර යාමට ලැම්බඩයකින් ඔතා තිබිය යුතුය (හෝ ඒ හා සමානව ඉදිකරන ලද partialහෝ operatorක්‍රියාකාරකම් ආදිය) filter, එවිට ලැයිස්තුගත කිරීම් ජයග්‍රහණය වේ.
abarnert

5
Python3 හි අවම වශයෙන් නැවත පැමිණීම filterපෙරහන් උත්පාදක වස්තුවක් ලැයිස්තුවක් නොවන බව පැවසිය යුතුය.
මැටියෝ ෆර්ලා

Answers:


605

විවිධ පුද්ගලයින් සඳහා අලංකාරය කොතරම් වෙනස් වේද යන්න පුදුමයකි. ලැයිස්තු අවබෝධය filter+ ට වඩා පැහැදිලි බව මට පෙනේ lambda, නමුත් ඔබට පහසු ඕනෑම දෙයක් භාවිතා කරන්න.

ඔබගේ භාවිතය මන්දගාමී විය හැකි කරුණු දෙකක් තිබේ filter.

පළමුවැන්න ශ්‍රිත ඇමතුම් උඩිස් ය: ඔබ පයිතන් ශ්‍රිතයක් භාවිතා කළ විගසම (නිර්මාණය කර defහෝ වේවා lambda) ලැයිස්තු අවබෝධයට වඩා පෙරණය මන්දගාමී වනු ඇත. එය නිසැකවම පාහේ ප්‍රමාණවත් නොවන අතර, ඔබේ කේතය කාලානුරූපව තබා එය බාධකයක් බව සොයා ගන්නා තෙක් ඔබ කාර්ය සාධනය ගැන වැඩි යමක් නොසිතිය යුතුය, නමුත් වෙනස පවතිනු ඇත.

අදාළ විය හැකි අනෙක් පොදු කාර්යය නම්, ලැම්බඩාට විෂය පථ විචල්‍යයකට ප්‍රවේශ වීමට බල කිරීමයි value. එය දේශීය විචල්‍යයකට ප්‍රවේශ වීමට වඩා මන්දගාමී වන අතර පයිතන් 2.x හි ලැයිස්තු අවබෝධය ප්‍රවේශ වන්නේ දේශීය විචල්‍යයන්ට පමණි. ඔබ පයිතන් 3.x භාවිතා කරන්නේ නම් ලැයිස්තු අවබෝධය වෙනම ශ්‍රිතයක් තුළ ක්‍රියාත්මක වන අතර එමඟින් එය valueවසා දැමීමක් හරහා ප්‍රවේශ වන අතර මෙම වෙනස අදාළ නොවේ.

සලකා බැලිය යුතු අනෙක් විකල්පය නම් ලැයිස්තු අවබෝධය වෙනුවට ජනක යන්ත්‍රයක් භාවිතා කිරීමයි:

def filterbyvalue(seq, value):
   for el in seq:
       if el.attribute==value: yield el

ඉන්පසු ඔබේ ප්‍රධාන කේතයේ (කියවීමේ හැකියාව සැබවින්ම වැදගත් වන්නේ) ඔබ ලැයිස්තු අවබෝධය සහ පෙරණය යන දෙකම ප්‍රතිස්ථාපනය කර බලාපොරොත්තුවෙන් අර්ථවත් ශ්‍රිත නාමයක් ලබා දී ඇත.


70
උත්පාදක යන්ත්රය සඳහා +1. ජනක යන්ත්‍ර විස්මිත විය හැකි ආකාරය පෙන්වන ඉදිරිපත් කිරීමකට මගේ නිවසේ සබැඳියක් ඇත. ඔබ ද හුදෙක් වෙනස් කිරීම මගින් එක් ජනන යන්ත්රයක ප්රකාශනය සමග ලැයිස්තුව අවබෝධය වෙනුවට හැකි []කිරීමට (). එසේම, ලැයිස්තු සම්පාදනය වඩාත් අලංකාර බව මම එකඟ වෙමි.
වේන් වර්නර්

1
ඇත්ත වශයෙන්ම, නැත - පෙරණය වේගවත් වේ. Stackoverflow.com/questions/5998245/…
skqr

2
kskqr මිණුම් සලකුණු සඳහා කාලරාමුව භාවිතා කිරීම වඩා හොඳය, නමුත් කරුණාකර ඔබට filterපයිතන් ඇමතුම් ආපසු ගැනීමේ ශ්‍රිතයක් භාවිතා කිරීම වේගවත් යැයි සොයා ගත හැකි උදාහරණයක් දෙන්න .
ඩන්කන්

8
genera tnq177 එය ජනක යන්ත්‍ර පිළිබඳ ඩේවිඩ් බීස්ලිගේ ඉදිරිපත් කිරීමකි - dabeaz.com/generator
වේන් වර්නර්

2
@ වික්ටර්ස්ක්‍රෝඩර් ඔව්, සමහර විට මම අපැහැදිලි විය. මම කියන්නට උත්සාහ කළ දෙය නම් ප්‍රධාන කේතයේ ඔබට විශාල පින්තූරය දැක ගත හැකි වීමයි. කුඩා උපකාරක ශ්‍රිතයේ දී ඔබට අවශ්‍ය වන්නේ එම එක් ශ්‍රිතයක් ගැන පමණක් වන අතර, පිටතින් සිදුවන වෙනත් දේ නොසලකා හැරිය හැකිය.
ඩන්කන්

243

මෙය පයිතන්හි තරමක් ආගමික කාරණයක්. වුවත් ගයිඩෝ ඉවත් සලකා map, filterසහ reducePython 3 සිට , අවසානයේ දී පමණක් බව ප්රහාරයකට ප්රමාණවත් විය reduceඉදි වීම් වලින් ඉදිරිපත් කරන ලදී functools.reduce .

පුද්ගලිකව මට ලැයිස්තු අවබෝධය කියවීමට පහසු වේ. [i for i in list if i.attribute == value]සියලු හැසිරීම් පෙරහන් ශ්‍රිතය තුළ නොව මතුපිට ඇති බැවින් ප්‍රකාශනයෙන් සිදුවන්නේ කුමක්ද යන්න වඩාත් පැහැදිලිය .

ප්‍රවේශයන් දෙක අතර කාර්ය සාධන වෙනස ආන්තික බැවින් මම ඕනෑවට වඩා කරදර නොවෙමි. මම මෙය සැබවින්ම ප්‍රශස්තිකරණය කරන්නේ එය ඔබගේ යෙදුමේ ඇති බාධකය බව ඔප්පු වුවහොත් පමණි.

ද සිට BDFL අවශ්ය filterනියත වශයෙන්ම ස්වයංක්රීයව ලැයිස්තුව comprehensions වැඩි Pythonic කරවන භාෂාවේ ගොස් ;-)


1
ගයිඩෝගේ ආදානයට සබැඳි වලට ස්තූතියි, වෙන කිසිවක් මා සඳහා නොමැති නම් එයින් අදහස් කරන්නේ මම ඒවා තවදුරටත් භාවිතා නොකිරීමට උත්සාහ කරමි, එවිට මට පුරුද්ද නොලැබෙන අතර මම එම ආගමට සහයෝගය
නොදක්වන්නෙමි

2
නමුත් අඩු කිරීම සරල මෙවලම් සමඟ කළ හැකි වඩාත් සංකීර්ණ වේ! අවබෝධය සමඟ ප්‍රතිස්ථාපනය කිරීම සඳහා සිතියම සහ පෙරණය ඉතා සුළුය!
njzk2

9
අඩු කිරීම පයිතන් 3 හි අඩු කර ඇති බව දැන සිටියේ නැත. තීක්ෂ්ණ බුද්ධියට ස්තූතියි! අඩු කිරීම () තවමත් පයිස්පාර්ක් වැනි බෙදා හරින ලද පරිගණක සඳහා බෙහෙවින් උපකාරී වේ. මම හිතන්නේ එය වැරැද්දක් ..
තාගර්

1
AgTagar ඔබට තවමත් භාවිතා කළ හැකිය අඩු කිරීම මඟින් ඔබට එය functools වෙතින් ආනයනය කළ යුතුය
icc97

73

ඕනෑම වේග වෙනසක් කුඩා වීමට බැඳී ඇති හෙයින්, පෙරහන් භාවිතා කිරීම හෝ ලැයිස්තු අවබෝධය රස බැලීමේ කාරණයකට පැමිණේ. පොදුවේ ගත් කල මම අවබෝධය භාවිතා කිරීමට නැඹුරු වෙමි (මෙහි වෙනත් බොහෝ පිළිතුරු සමඟ එකඟ වන බව පෙනේ), නමුත් මා කැමති එක් අවස්ථාවක් filterතිබේ.

බොහෝ විට භාවිතා වන අවස්ථාවක් වන්නේ පුරෝකථනය කළ P (x) ට යටත්ව සමහර නැවත කළ හැකි X හි අගයන් ඉවත් කිරීමයි:

[x for x in X if P(x)]

නමුත් සමහර විට ඔබට පළමුව යම් ශ්‍රිතයක් අගයන්ට අදාළ කිරීමට අවශ්‍ය වේ:

[f(x) for x in X if P(f(x))]


නිශ්චිත උදාහරණයක් ලෙස, සලකා බලන්න

primes_cubed = [x*x*x for x in range(1000) if prime(x)]

මම හිතන්නේ මෙය භාවිතයට වඩා තරමක් හොඳ බව පෙනේ filter. නමුත් දැන් සලකා බලන්න

prime_cubes = [x*x*x for x in range(1000) if prime(x*x*x)]

මෙම අවස්ථාවේ දී අපට අවශ්‍ය වන්නේ filterපශ්චාත් ගණනය කළ අගයට එරෙහිව ය. Ube නකය දෙවරක් ගණනය කිරීමේ ගැටලුවට අමතරව (වඩා මිල අධික ගණනය කිරීමක් සිතන්න), ඩ්‍රයි සෞන්දර්යය උල්ලං ting නය කරමින් ප්‍රකාශනය දෙවරක් ලිවීමේ ගැටලුවක් තිබේ . මෙම අවස්ථාවේ දී මම භාවිතා කිරීමට සුදුසු වනු ඇත

prime_cubes = filter(prime, [x*x*x for x in range(1000)])

8
වෙනත් ලැයිස්තු අවබෝධයක් හරහා ප්‍රයිම් භාවිතා කිරීම ගැන ඔබ නොසිතන්නේද? වැනි[prime(i) for i in [x**3 for x in range(1000)]]
viki.omega9

24
x*x*xප්‍රාථමික සංඛ්‍යාවක් විය නොහැක, එයට ඇති පරිදි x^2සහ xසාධකයක් ලෙස, උදාහරණය ගණිතමය ආකාරයකින් සැබවින්ම අර්ථවත් නොවේ, නමුත් සමහර විට එය තවමත් උපකාරී වේ. (සමහර විට අපට වඩා හොඳ යමක් සොයා ගත හැකිද?)
සෙල්ෆීර් කල්ට්ස්ටාල්

4
අපට මතකය අනුභව කිරීමට අවශ්‍ය නැතිනම් අවසාන උදාහරණය වෙනුවට අපි උත්පාදක ප්‍රකාශනයක් භාවිතා කළ හැකි බව සලකන්න:prime_cubes = filter(prime, (x*x*x for x in range(1000)))
මාටීන් උල්හාක්

4
AteMateenUlhaq prime_cubes = [1]මතකය සහ cpu චක්‍ර දෙකම සුරැකීමට මෙය ප්‍රශස්තිකරණය කළ හැකිය ;-)
ඩෙනිස් කෘපෙනික්

7
Enn ඩෙනිස් කෘපෙනික් හෝ ඒ වෙනුවට,[]
මාටීන් උල්හාක්

30

filter“වේගවත් මාර්ගය” විය හැකි නමුත් , කාර්ය සාධනය අතිශයින්ම තීරණාත්මක නම් මිස “පයිතොනික් ක්‍රමය” එවැනි දේ ගැන සැලකිලිමත් නොවනු ඇත (එවැනි අවස්ථාවක ඔබ පයිතන් භාවිතා නොකරනු ඇත!).


10
බොහෝ විට දැකිය හැකි තර්කයකට ප්‍රමාද අදහස් දැක්වීම: සමහර විට එය 10 වෙනුවට පැය 5 කින් විශ්ලේෂණයක් පවත්වා ගෙන යාමේ වෙනසක් ඇති කරයි, සහ පයිතන් කේතය ප්‍රශස්තිකරණය කිරීම සඳහා පැයක් ගත කිරීමෙන් එය සාක්ෂාත් කරගත හැකි නම්, එය වටී (විශේෂයෙන් එකක් නම් වේගවත් භාෂාවලින් නොව පයිතන් සමඟ සැපපහසුයි).
bli

නමුත් වඩා වැදගත් දෙය නම් මූලාශ්‍ර කේතය එය කියවීමට හා තේරුම් ගැනීමට උත්සාහ කිරීම මන්දගාමී වීමයි!
thoni56

21

මම හිතුවා මම එය පයිතන් 3 හි එකතු කරන්නම්, පෙරණය () ඇත්ත වශයෙන්ම අනුකාරක වස්තුවක්, එබැවින් පෙරහන් ලැයිස්තුව තැනීම සඳහා ඔබේ පෙරහන් ක්‍රමවේදය ඇමතුම් ලැයිස්තුවට () යැවිය යුතුය. එබැවින් පයිතන් 2 හි:

lst_a = range(25) #arbitrary list
lst_b = [num for num in lst_a if num % 2 == 0]
lst_c = filter(lambda num: num % 2 == 0, lst_a)

ලැයිස්තු b සහ c එකම අගයන් ඇති අතර, පෙරණය () සමාන වන විට සම්පූර්ණ කරන ලදි [x නම් y සඳහා x සඳහා x නම් z]. කෙසේ වෙතත්, 3 දී, මෙම කේතයම පෙරහන් ලැයිස්තුවක් නොව පෙරහන් වස්තුවක් සහිත c ලැයිස්තුවෙන් ඉවත් වේ. එකම අගයන් 3 කින් නිපදවීමට:

lst_a = range(25) #arbitrary list
lst_b = [num for num in lst_a if num % 2 == 0]
lst_c = list(filter(lambda num: num %2 == 0, lst_a))

ගැටළුව වන්නේ ලැයිස්තුව () එහි තර්කය ලෙස නැවත සැකසිය හැකි අතර එම තර්කයෙන් නව ලැයිස්තුවක් නිර්මාණය කිරීමයි. මෙහි ප්‍රති result ලය වනුයේ පයිතන් 3 හි පෙරණය භාවිතා කිරීම [x සඳහා x සඳහා y නම් z] ක්‍රමයට වඩා දෙගුණයක් පමණ කාලයක් ගත වන බැවිනි. මන්දයත් ඔබට පෙරණය () සහ මුල් ලැයිස්තුවෙන් ලැබෙන ප්‍රතිදානය ඉක්මවා යා යුතු බැවිනි.


14

වැදගත් වෙනසක් නම් list, පෙරණය a මඟින් නැවත ලබා දෙන අතර filter, ඔබට එය මෙන් හැසිරවිය නොහැක list(එනම්: lenඑය අමතන්න , එය නැවත පැමිණීම සමඟ ක්‍රියා නොකරයි filter).

මගේම ස්වයං ඉගෙනීම මා හා සමාන ගැටලුවකට යොමු විය.

එසේ පැවසුවහොත්, ප්‍රති listfrom ල ලබා ගැනීමට ක්‍රමයක් තිබේ නම් filter, ඔබ වැනි දෙයක් .NET හි ඔබ කරන විට, ඔබ එය කරන විට lst.Where(i => i.something()).ToList(), එය දැන ගැනීමට මට කුතුහලයක් ඇත.

සංස්කරණය කරන්න: පයිතන් 3 සඳහා මෙය 2 මිස 2 නොවේ (අදහස් දැක්වීමේ සාකච්ඡාව බලන්න).


4
පෙරණය මඟින් ලැයිස්තුවක් ලබා දෙන අතර අපට එය මත ලෙන් භාවිතා කළ හැකිය. අවම වශයෙන් මගේ පයිතන් 2.7.6 හි.
thiruvenkadam

7
පයිතන් 3 හි එය එසේ නොවේ. a = [1, 2, 3, 4, 5, 6, 7, 8] f = filter(lambda x: x % 2 == 0, a) lc = [i for i in a if i % 2 == 0] >>> type(f) <class 'filter'> >>> type(lc) <class 'list'>
ඇඩෙනැක්

4
"එහි ප්‍රති ing ලයක් ලෙස ලැයිස්තුවක් ලබා ගැනීමට ක්‍රමයක් තිබේ නම් ... එය දැන ගැනීමට මට කුතුහලයක් ඇත". ප්‍රති list()result ලය අමතන්න : list(filter(my_func, my_iterable)). තවද ඔබ විසින් විස්ථාපනය කළ හැකි listසමග set, හෝ tuple, හෝ iterable ගත වන බව දෙයක්. නමුත් ක්‍රියාකාරී ක්‍රමලේඛකයින් හැර වෙනත් ඕනෑම කෙනෙකුට, filterපැහැදිලිව පරිවර්තනය කිරීම වෙනුවට ලැයිස්තු අවබෝධය භාවිතා කිරීම නඩුව වඩාත් ශක්තිමත් වේ list.
ස්ටීව් ජෙසොප්

10

දෙවන ක්‍රමය වඩාත් කියවිය හැකි බව මට පෙනේ. අභිප්‍රාය කුමක්දැයි එය ඔබට හරියටම කියයි: ලැයිස්තුව පෙරහන් කරන්න.
PS: විචල්ය නාමයක් ලෙස 'ලැයිස්තුව' භාවිතා නොකරන්න


8

පෙරණය යනු එයයි. එය ලැයිස්තුවක අංග පෙරහන් කරයි. අර්ථ දැක්වීම එකම ලෙස සඳහන් කර ඇති ආකාරය ඔබට දැක ගත හැකිය (මා කලින් සඳහන් කළ නිල ලේඛන සබැඳියේ). ලැයිස්තු අවබෝධය යනු පෙර ලැයිස්තුවේ යම් දෙයක් ක්‍රියාත්මක කිරීමෙන් පසු නව ලැයිස්තුවක් නිපදවන දෙයකි (පෙරණය සහ ලැයිස්තු අවබෝධය යන දෙකම නව ලැයිස්තුවක් නිර්මාණය කරන අතර පැරණි ලැයිස්තුව වෙනුවට ක්‍රියාත්මක නොවේ. මෙහි නව ලැයිස්තුවක් ලැයිස්තුවක් වැනි ය , කියන්න, සම්පූර්ණයෙන්ම නව දත්ත වර්ගයකි. පූර්ණ සංඛ්‍යා නූල් බවට පරිවර්තනය කිරීම වැනි)

ඔබේ උදාහරණයේ දී, අර්ථ දැක්වීම අනුව ලැයිස්තු අවබෝධයට වඩා පෙරණය භාවිතා කිරීම වඩා හොඳය. කෙසේ වෙතත්, ඔබට අවශ්‍ය නම්, ලැයිස්තු මූලද්‍රව්‍යයන්ගෙන් වෙනත්_ප්‍රතිපත්තියක් කියන්න, ඔබේ උදාහරණයේ දී නව ලැයිස්තුවක් ලෙස ලබා ගත යුතුය, එවිට ඔබට ලැයිස්තු අවබෝධය භාවිතා කළ හැකිය.

return [item.other_attribute for item in my_list if item.attribute==value]

පෙරණය සහ ලැයිස්තු අවබෝධය ගැන මට ඇත්ත වශයෙන්ම මතක ඇති ආකාරය මෙයයි. ලැයිස්තුවක් තුළ ඇති කරුණු කිහිපයක් ඉවත් කර අනෙක් අංග නොවෙනස්ව තබා ගන්න, පෙරණය භාවිතා කරන්න. මූලද්‍රව්‍යයන්හි ඔබ විසින්ම යම් තර්කනයක් භාවිතා කර යම් අරමුණක් සඳහා සුදුසු වතුර දැමූ ලැයිස්තුවක් සාදන්න, ලැයිස්තු අවබෝධය භාවිතා කරන්න.


2
අඩු ඡන්දය ප්‍රකාශ කිරීමට හේතුව දැන ගැනීමට ලැබීම ගැන මම සතුටු වන අතර එමඟින් අනාගතයේ කොතැනකවත් එය නැවත නොකෙරේ.
thiruvenkadam

පෙරණය සහ ලැයිස්තු අවබෝධය අර්ථ දැක්වීම අවශ්‍ය නොවීය, මන්ද ඒවායේ අර්ථය විවාදයට භාජනය නොවීය. ලැයිස්තු අවබෝධය “නව” ලැයිස්තු සඳහා පමණක් භාවිතා කළ යුතු නමුත් ඉදිරිපත් නොකෙරේ.
ඇගෝස්

ෆිල්ටරය ඔබට නඩුවකට සත්‍ය වන එකම මූලද්‍රව්‍යයන් සහිත ලැයිස්තුවක් ලබා දෙන බව පැවසීමට මම අර්ථ දැක්වීම භාවිතා කළ නමුත් ලැයිස්තු අවබෝධය සමඟින් අපට මූලද්‍රව්‍යයන්ම වෙනස් කළ හැකිය. නමුත් ගත යුතු කරුණ :-)
thiruvenkadam

7

සාමාන්‍යයෙන් filterබිල්ඩින් ශ්‍රිතයක් භාවිතා කරන්නේ නම් එය තරමක් වේගවත් වේ.

ඔබේ නඩුවේ ලැයිස්තු අවබෝධය තරමක් වේගවත් වනු ඇතැයි මම බලාපොරොත්තු වෙමි


python -m timeit 'පෙරණය (ලැම්බඩා x: x [1,2,3,4,5], පරාසය (10000000))' ලූප 10, හොඳම ලූපයකට තත්පර 3: 1.44 තත්පරයට පයිතන්-එම් ටයිමිට් '[x සඳහා x පරාසය තුළ (10000000) x [1,2,3,4,5]] 'ලූප 10 ක් නම්, හොඳම ලූපයකට 3: 860 msec වේ.
giaosudau

p සෙප්ඩෝ, ලැම්බඩා ශ්‍රිත බිල්ඩින් නොවේ. පසුගිය වසර 4 තුළ ලැයිස්තු අවබෝධය වැඩිදියුණු වී ඇත - දැන් බිල්ඩින් කාර්යයන් සමඟ වුවද වෙනස නොසැලකිලිමත් වේ
ජෝන් ලා රූයි

4

ලැයිස්තු අවබෝධයෙන් පසුව යමක් පෙරීමට අවශ්‍ය විට මම භාවිතා කරන කෙටි කෑල්ලක් මෙන්න . පෙරණය, ලැම්බඩා සහ ලැයිස්තු වල එකතුවක් (වෙනත් ආකාරයකින් බළලෙකුගේ පක්ෂපාතිත්වය සහ බල්ලෙකුගේ පිරිසිදුකම ලෙස හැඳින්වේ).

මෙම අවස්ථාවේ දී මම ගොනුවක් කියවමින්, හිස් රේඛා ඉවත් කිරීම, රේඛා විවරණය කිරීම සහ රේඛාවක් පිළිබඳ අදහස් දැක්වීමෙන් පසුව ඕනෑම දෙයක්:

# Throw out blank lines and comments
with open('file.txt', 'r') as lines:        
    # From the inside out:
    #    [s.partition('#')[0].strip() for s in lines]... Throws out comments
    #   filter(lambda x: x!= '', [s.part... Filters out blank lines
    #  y for y in filter... Converts filter object to list
    file_contents = [y for y in filter(lambda x: x != '', [s.partition('#')[0].strip() for s in lines])]

ඇත්ත වශයෙන්ම මෙය ඉතා සුළු කේතයකින් බොහෝ දේ අත්කර ගනී. මම හිතන්නේ එය එක් පේළියක පහසුවෙන් තේරුම් ගත හැකි තරමට වඩා තර්කානුකූල විය හැකි අතර කියවීමේ හැකියාව වැදගත් වේ.
සෙල්ෆීර් කල්ට්ස්ටාල්

ඔබට මෙය මෙසේ ලිවිය හැකියfile_contents = list(filter(None, (s.partition('#')[0].strip() for s in lines)))
ස්ටීව් ජෙසොප්

4

පිළිගත් පිළිතුරට අමතරව, ලැයිස්තු අවබෝධය වෙනුවට පෙරණය භාවිතා කළ යුතු අවස්ථා තිබේ. ලැයිස්තුව වෙනස් කළ නොහැකි නම් ඔබට එය ලැයිස්තු අවබෝධයකින් සෘජුවම සැකසිය නොහැක. සැබෑ ලෝක උදාහරණයක් නම් ඔබ pyodbcදත්ත සමුදායකින් ප්‍රති results ල කියවීමට භාවිතා කරන්නේ නම් . ප්‍රති The fetchAll()cursorවෙනස් කළ නොහැකි ලැයිස්තුවකි. මෙම තත්වය තුළ, ආපසු ලබා දුන් ප්‍රති results ල සෘජුවම හැසිරවීමට පෙරණය භාවිතා කළ යුතුය:

cursor.execute("SELECT * FROM TABLE1;")
data_from_db = cursor.fetchall()
processed_data = filter(lambda s: 'abc' in s.field1 or s.StartTime >= start_date_time, data_from_db) 

ඔබ මෙහි ලැයිස්තු අවබෝධය භාවිතා කරන්නේ නම් ඔබට දෝෂය ලැබෙනු ඇත:

TypeError: වෙනස් කළ නොහැකි වර්ගය: 'list'


2
සියලුම ලැයිස්තු වෙනස් කළ නොහැකි ය. >>> hash(list()) # TypeError: unhashable type: 'list'දෙවනුව මෙය හොඳින් ක්‍රියාත්මක වේ:processed_data = [s for s in data_from_db if 'abc' in s.field1 or s.StartTime >= start_date_time]
තෝමස්

1
"ලැයිස්තුව වෙනස් කළ නොහැකි නම් ඔබට එය ලැයිස්තු අවබෝධයකින් සෘජුවම සැකසිය නොහැක." මෙය සත්‍ය නොවන අතර, කෙසේ වෙතත් සියලුම ලැයිස්තු වෙනස් කළ නොහැක.
juanpa.arrivillaga

3

higher order functions filterසහ හුරුපුරුදු වීමට මට යම් කාලයක් ගත විය map. ඒ නිසා මම ඔවුන් සමඟ පුරුදු වී සිටිමි. ඇත්ත වශයෙන්ම filterඑය සත්‍යය දේ තබා ගැනීමෙන් පෙරහන් කරන බව පැහැදිලිව පෙනෙන නිසා මම ඇත්තෙන්ම කැමතියි functional programming.

ඊට පස්සේ මම මේ කොටස කියෙව්වා (චතුර ලෙස පයිතන් පොත):

සිතියම සහ පෙරහන් කාර්යයන් තවමත් පයිතන් 3 හි ගොඩනගා ඇත, නමුත් ලැයිස්තු අවබෝධය සහ උත්පාදක හිටපු මුද්‍රණ හඳුන්වා දීමෙන් පසුව ඒවා එතරම් වැදගත් නොවේ. ලැයිස්තුගත කිරීමක් හෝ ජෙනෙක්ස් එකක් සිතියම සහ පෙරණය ඒකාබද්ධව සිදු කරයි, නමුත් එය වඩාත් කියවිය හැකිය.

දැන් මම සිතන්නේ, ලැයිස්තු අවබෝධය වැනි දැනටමත් පුළුල් ලෙස ව්‍යාප්ත වී ඇති මෝඩයන් සමඟ ඔබට එය සාක්ෂාත් කරගත හැකි නම් filter/ සංකල්පයට කරදර වන්නේ ඇයි? mapතව දුරටත් mapsසහ filtersකාරුණික කාර්යයන් වේ. මෙම අවස්ථාවේ දී මම Anonymous functionsලැම්බඩාස් භාවිතා කිරීමට කැමැත්තෙමි .

අවසාන වශයෙන්, එය පරීක්‍ෂා කිරීම සඳහා, මම ක්‍රම දෙකම ( mapසහ listComp) කාලානුරූපව තබා ඇති අතර, ඒ පිළිබඳ තර්ක කිරීම සාධාරණීකරණය කරන අදාළ වේග වෙනසක් මා දුටුවේ නැත.

from timeit import Timer

timeMap = Timer(lambda: list(map(lambda x: x*x, range(10**7))))
print(timeMap.timeit(number=100))

timeListComp = Timer(lambda:[(lambda x: x*x) for x in range(10**7)])
print(timeListComp.timeit(number=100))

#Map:                 166.95695265199174
#List Comprehension   177.97208347299602

0

කුතුහලයෙන් යුතුව, පයිතන් 3 හි, ලැයිස්තු අවබෝධයට වඩා වේගයෙන් පෙරණය ක්‍රියා කරන බව මට පෙනේ.

මම නිතරම සිතුවේ ලැයිස්තු අවබෝධය වඩාත් ක්‍රියාකාරී වනු ඇති බවයි. වැනි දෙයක්: [නම නොමැති නම් brand_names_db හි නම සඳහා නම] ජනනය කරන ලද බයිට් කේතය ටිකක් හොඳයි.

>>> def f1(seq):
...     return list(filter(None, seq))
>>> def f2(seq):
...     return [i for i in seq if i is not None]
>>> disassemble(f1.__code__)
2         0 LOAD_GLOBAL              0 (list)
          2 LOAD_GLOBAL              1 (filter)
          4 LOAD_CONST               0 (None)
          6 LOAD_FAST                0 (seq)
          8 CALL_FUNCTION            2
         10 CALL_FUNCTION            1
         12 RETURN_VALUE
>>> disassemble(f2.__code__)
2           0 LOAD_CONST               1 (<code object <listcomp> at 0x10cfcaa50, file "<stdin>", line 2>)
          2 LOAD_CONST               2 ('f2.<locals>.<listcomp>')
          4 MAKE_FUNCTION            0
          6 LOAD_FAST                0 (seq)
          8 GET_ITER
         10 CALL_FUNCTION            1
         12 RETURN_VALUE

නමුත් ඒවා ඇත්ත වශයෙන්ම මන්දගාමී ය:

   >>> timeit(stmt="f1(range(1000))", setup="from __main__ import f1,f2")
   21.177661532000116
   >>> timeit(stmt="f2(range(1000))", setup="from __main__ import f1,f2")
   42.233950221000214

8
වලංගු නොවන සංසන්දනය . පළමුව, ඔබ ලැම්බඩා ශ්‍රිතයක් පෙරහන් අනුවාදයට නොයවන අතර එමඟින් එය අනන්‍යතා ශ්‍රිතයට පෙරනිමිය වේ. නිර්වචනය විට if not Noneලැයිස්තුව අවබෝධය ඔබ සිටින යම් ලැම්ඩා කාර්යය (දැනුම් නිර්ණය MAKE_FUNCTIONප්රකාශයක්). දෙවනුව, Noneප්‍රති understanding ල වෙනස් වේ, මන්ද ලැයිස්තු අවබෝධ කර ගැනීමේ අනුවාදය මඟින් අගය පමණක් ඉවත් කරනු ඇති අතර පෙරහන් අනුවාදය සියලු "ව්‍යාජ" අගයන් ඉවත් කරයි. එසේ පැවසීමෙන් මයික්‍රොබෙන්ච්මාර්ක් කිරීමේ සම්පූර්ණ අරමුණ නිෂ් .ල ය. ඒවා මිලියනයක පුනරාවර්තන වේ, වාර 1k අයිතම! වෙනස නොසැලකිලිමත් ය .
වික්ටර් ෂ්‍රෝඩර්

-7

මගේ ගන්න

def filter_list(list, key, value, limit=None):
    return [i for i in list if i[key] == value][:limit]

3
iකිසි විටෙකත් එය යැයි dictනොකියන අතර අවශ්‍යතාවයක් නොමැත limit. ඒ හැර, OP යෝජනා කළ දෙයට වඩා මෙය වෙනස් වන්නේ කෙසේද සහ එය ප්‍රශ්නයට පිළිතුරු දෙන්නේ කෙසේද?
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.