7

की अनुमानित तुलना के साथ मुझे दो फाइलों की तुलना करने में कोई समस्या है। मूल रूप से, मुझे क्या करना चाहते हैं दो फ़ाइलों के बीच एक UNIX- जैसे diff उदाहरण के लिए, है:पायथन में दो फाइलों के "अस्पष्ट" अंतर उत्पन्न करें, फ्लोट्स

$ diff -u बाएं फ़ाइल पर राइट-फ़ाइल

हालांकि मेरी दो फ़ाइलों तैरता होता है; और क्योंकि ये फ़ाइलें अलग-अलग आर्किटेक्चर पर उत्पन्न हुई थीं (लेकिन एक ही चीजों की गणना), फ्लोटिंग मान बिल्कुल समान नहीं हैं (वे कह सकते हैं, 1e-10 कह सकते हैं)। लेकिन मैं फ़ाइलों को 'diffing' द्वारा खोजना चाहता हूं जो मुझे महत्वपूर्ण मतभेद मानते हैं (उदाहरण के लिए अंतर 1e-4 से अधिक है); यूनिक्स कमांड diff का उपयोग करते समय, मुझे लगभग सभी मेरी लाइनें मिलती हैं जिनमें फ़्लोटिंग वैल्यू अलग-अलग होते हैं! यह मेरी समस्या है: मैं 'diff -u' जैसी परिणामी diff कैसे प्राप्त कर सकता हूं, लेकिन फ्लोट की तुलना के संबंध में कम प्रतिबंधों के साथ?

मैंने सोचा कि मैं ऐसा करने के लिए एक पायथन की लिपि लिखूंगा, और मॉड्यूल difflib पता चला जो diff-like तुलना प्रदान करता है। लेकिन मुझे मिले दस्तावेज बताते हैं कि इसका उपयोग कैसे करें (एक विधि के माध्यम से), और आंतरिक वस्तुओं को समझाता है, लेकिन मुझे अपनी जरूरतों को पूरा करने के लिए एक difflib ऑब्जेक्ट को कस्टमाइज़ करने के तरीके के बारे में कुछ भी नहीं मिल रहा है (जैसे केवल तुलना विधि को फिर से लिखना या ऐसे) ... मुझे लगता है कि एक एकीकृत अंतर को पुनः प्राप्त करने के लिए एक समाधान हो सकता है, और इसे 'झूठी' मतभेदों को हटाने के लिए इसे 'मैन्युअल' पार्स कर सकता है, इससे यह सुरुचिपूर्ण नहीं है; मैं पहले से ही मौजूदा ढांचे का उपयोग करना पसंद करूंगा।

तो, क्या कोई इस लिब को कस्टमाइज़ करने के बारे में जानता है ताकि मैं जो चाहूं वह कर सकूं? या कम से कम मुझे सही दिशा में इंगित करें ... यदि पायथन में नहीं है, तो शायद एक शैल स्क्रिप्ट नौकरी के लिए हो सकती है?

किसी भी मदद की सराहना की जाएगी! आपके जवाब के लिए पहले से ही धन्यवाद!

+1

शायद तुम यह भी पसंद: [फजी स्ट्रिंग तुलना के लिए अच्छा अजगर मॉड्यूल ?] (http://stackoverflow.com/questions/682367/good-python-modules-for-fuzzy-string-comparison) – miku

+0

एक आसान विकल्प पूर्व-प्रक्रिया फ़ाइल और प्रारूप वांछित सटीकता के लिए सही ढंग से फ़्लोट करना होगा –

+0

कृपया नमूना इनपुट फ़ाइलों से संबंधित कुछ पंक्तियों को पोस्ट करें? – smci

उत्तर

4

आपके मामले में हम general case विशेषज्ञ हैं: इससे पहले कि हम चीजों को अलग कर सकें, हमें फ्लोट युक्त लाइनों को पहचानने और अलग-अलग संभालने की आवश्यकता है। यहां एक बुनियादी दृष्टिकोण है, यदि आप डेल्टा, संदर्भ की रेखाएं आदि बनाना चाहते हैं तो आप इस पर निर्माण कर सकते हैं। ध्यान दें कि फ़ज़ीज़ करना आसान है-स्ट्रिंग्स की बजाय वास्तविक फ्लोट के रूप में फ्लोट की तुलना करें (हालांकि आप कॉलम-बाय-कॉलम को कोड कर सकते हैं और 1-ई 4 के बाद वर्णों को अनदेखा कर सकते हैं)।

import re 

float_pat = re.compile('([+-]?\d*\.\d*)') 
def fuzzydiffer(line1,line2): 
    """Perform fuzzy-diff on floats, else normal diff.""" 
    floats1 = float_pat.findall(line1) 
    if not floats1: 
     pass # run your usual diff() 
    else: 
     floats2 = float_pat.findall(line2) 
     for (f1,f2) in zip(floats1,floats2): 
      (col1,col2) = line1.index(f1),line2.index(f2) 
      if not fuzzy_float_cmp(f1,f2): 
       print "Lines mismatch at col %d", col1, line1, line2 
      continue 
    # or use a list comprehension like all(fuzzy_float_cmp(f1,f2) for f1,f2 in zip(float_pat.findall(line1),float_pat.findall(line2))) 
    #return match 

def fuzzy_float_cmp(f1,f2,epsilon=1e-4): 
    """Fuzzy-compare two strings representing floats.""" 
    float1,float2 = float(f1),float(f2) 
    return (abs(float1-float2) < epsilon) 

कुछ परीक्षण:

fuzzydiffer('text: 558.113509766 +23477547.6407 -0.867086648057 0.009291785451', 
'text: 558.11351 +23477547.6406 -0.86708665 0.009292000001') 

और एक बोनस के रूप में, यहाँ एक संस्करण है कि प्रकाश डाला गया स्तंभ-डिफ है:

import re 

float_pat = re.compile('([+-]?\d*\.\d*)') 
def fuzzydiffer(line1,line2): 
    """Perform fuzzy-diff on floats, else normal diff.""" 
    floats1 = float_pat.findall(line1) 
    if not floats1: 
     pass # run your usual diff() 
    else: 
     match = True 
     coldiffs1 = ' '*len(line1) 
     coldiffs2 = ' '*len(line2) 
     floats2 = float_pat.findall(line2) 
     for (f1,f2) in zip(floats1,floats2): 
      (col1s,col2s) = line1.index(f1),line2.index(f2) 
      col1e = col1s + len(f1) 
      col2e = col2s + len(f2) 
      if not fuzzy_float_cmp(f1,f2): 
       match = False 
       #print 'Lines mismatch:' 
       coldiffs1 = coldiffs1[:col1s] + ('v'*len(f1)) + coldiffs1[col1e:] 
       coldiffs2 = coldiffs2[:col2s] + ('^'*len(f2)) + coldiffs2[col2e:] 
      #continue # if you only need to highlight first mismatch 
     if not match: 
      print 'Lines mismatch:' 
      print ' ', coldiffs1 
      print '< ', line1 
      print '> ', line2 
      print ' ', coldiffs2 
     # or use a list comprehension like 
     # all() 
     #return True 

def fuzzy_float_cmp(f1,f2,epsilon=1e-4): 
    """Fuzzy-compare two strings representing floats.""" 
    print "Comparing:", f1, f2 
    float1,float2 = float(f1),float(f2) 
    return (abs(float1-float2) < epsilon) 
संबंधित मुद्दे