سؤال

لدي بعض البيانات التي قمت بتخزينها في قائمة وإذا قمت بطباعة القائمة أرى ما يلي:

.
.
.
007 A000000 Y
007 B000000  5
007 C010100  1
007 C020100 ACORN FUND
007 C030100 N
007 C010200  2
007 C020200 ACORN INTERNATIONAL
007 C030200 N
007 C010300  3
007 C020300 ACORN USA
007 C030300 N
007 C010400  4
.
.
.

النقطات قبل وبعد التسلسل هي تمثيل أن هناك بيانات أخرى منظم مشابه ولكنها قد لا تكون جزءا من هذا البند السابع (007). إذا كانت القيمة الأولى في البند السابع "007 A000000 Y"، فأنا أريد إنشاء قائمة قاموس ببعض عناصر البيانات. يمكنني القيام بذلك وقدم ذلك من خلال التشغيل فقط من خلال جميع العناصر الموجودة في قائمتي ومقارنة قيمها إلى بعض قيم الاختبار للمتغيرات. على سبيل المثال خط رمز مثل:

if dataLine.find('007 B')==0:
    numberOfSeries=int(dataLine.split()[2])

ما أريد أن أفعله هو

if dataLine.find(''007 A000000 Y')==0:
    READ THE NEXT LINE RIGHT HERE

الآن أؤدي إلى التكرار من خلال القائمة بأكملها لكل دورة

أريد تقصير المعالجة لأن لدي حوالي 60 ألف ملفات لها ما بين 500 إلى 5000 خط في كل منها.

لقد فكرت في إنشاء مرجع آخر إلى القائمة وحساب Datalines حتى Dataline.Find ('007 A000000 Y') == 0. لكن هذا لا يبدو أنه هو الحل الأكثر أناقة.

هل كانت مفيدة؟

المحلول 5

حسنا، بينما كنت جوجلينج للتأكد من أنني قد غطت قواعدي التي صادفت فيها حلا:

أجد أنني نسيت أن أفكر في القوائم والقواميس على الرغم من أنني استخدمها. لدى Python بعض الأدوات القوية للعمل مع هذه الأنواع لتسريع قدرتك على التعامل معها.
أحتاج إلى شريحة حتى يتم الحصول على مراجع الشريحة بسهولة

beginPosit = tempans.index('007 A000000 Y')
endPosit = min([i for i, item in enumerate(tempans) if '008 ' in item])

حيث tempans هو datalist الآن أستطيع أن أكتب

for line in tempans[beginPosit:endPosit]:
    process each line

أعتقد أنني أجبت على سؤالي الخاص. لقد تعلمت الكثير من الإجابات الأخرى ونقدرها لكنني أعتقد أن هذا ما احتاجه

حسنا انا ذاهب لتعديل إجابتي. لقد تعلمت الكثير هنا ولكن بعض هذه الأشياء فوق رأسي ما زال وأريد الحصول على بعض الكود المكتوبة أثناء تعلم المزيد حول هذه الأداة الرائعة.

from itertools import takewhile
beginPosit = tempans.index('007 A000000 Y')
new=takewhile(lambda x: '007 ' in x, tempans[beginPosit:])

هذا يعتمد على إجابة سابقة على سؤال مماثل و ستيفن هووينج إجابه

نصائح أخرى

يمكنك استخدام itertools.groupby() لقطاع التسلسل الخاص بك في تسلسلات فرعية متعددة.

import itertools

for key, subseq in itertools.groupby(tempans, lambda s: s.partition(' ')[0]):
    if key == '007':
    for dataLine in subseq:
        if dataLine.startswith('007 B'):
        numberOfSeries = int(dataLine.split()[2])

itertools.dropwhile() سوف تعمل أيضا إذا كنت تريد حقا البحث حتى هذا الخط،

list(itertools.dropwhile(lambda s: s != '007 A000000 Y', tempans))
['007 A000000 Y',
 '007 B000000  5',
 '007 C010100  1',
 '007 C020100 ACORN FUND',
 '007 C030100 N',
 '007 C010200  2',
 '007 C020200 ACORN INTERNATIONAL',
 '007 C030200 N',
 '007 C010300  3',
 '007 C020300 ACORN USA',
 '007 C030300 N',
 '007 C010400  4',
 '.',
 '.',
 '.',
 '']

يمكنك قراءة البيانات في القاموس. على افتراض أنك تقرأ من كائن يشبه الملفات infile:

from collections import defaultdict
data = defaultdict(list)
for line in infile:
    elements = line.strip().split()
    data[elements[0]].append(tuple(elements[1:]))

الآن إذا كنت ترغب في قراءة الخط بعد "007 A000000 Y"، يمكنك القيام بذلك

# find the index of ('A000000', 'Y')
idx = data['007'].index(('A000000', 'Y'))
# get the next line
print data['007'][idx+1]

الصعوبة الوحيدة في استخدام جميع البيانات في القاموس هي أن القاموس الكبير حقا يمكن أن يصبح مزعجا. (هذا ما اعتدنا أن نسميه نهج "مصفوفة OLE كبيرة".)

حل لهذا هو بناء فهرس في القاموس، إنشاء رسم خرائط من المفتاح> إزاحة، باستخدام tell طريقة للحصول على قيمة إزاحة الملف. ثم يمكنك الرجوع إلى الخط مرة أخرى عن طريق البحث عن seek طريقة.

قلت أنك تريد القيام بذلك:

if dataLine.find(''007 A000000 Y')==0:
    READ THE NEXT LINE RIGHT HERE

من المفترض أن هذا ضمن حلقة "للادالين في البيانات".

بدلا من ذلك، يمكنك استخدام جهاز استئناف مباشر بدلا من في حلقة:

>>> i = iter(data)
>>> while i.next() != '007 A000000 Y': pass  # find your starting line
>>> i.next()  # read the next line
'007 B000000  5'

تذكر أيضا وجود 60K ملفات معالجتها. هل كلها تنسيقها بالمثل؟ هل يحتاجون إلى معالجة بشكل مختلف؟ إذا تمكن كل منهم جميعا بنفس الطريقة، فيمكنك التفكير في التسلسل معا في تدفق واحد:

def gfind( directory, pattern="*" ):
    for name in fnmatch.filter( os.listdir( directory ), pattern ):
        yield os.path.join( directory, name )

def gopen( names ):
    for name in names:
        yield open(name, 'rb')

def gcat( files ):
    for file in files:
        for line in file:
            yield line

data = gcat( gopen( gfind( 'C:\datafiles', '*.dat' ) ) )

يتيح لك ذلك معالجة جميع ملفاتك في مكيفاتك في مكرر واحد. لست متأكدا إذا كان ذلك يساعد وضعك الحالي لكنني اعتقدت أنه يستحق الذكر.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top