उद्धृत वर्गों को अनदेखा करते हुए एक स्ट्रिंग को विभाजित करें

इस तरह की एक स्ट्रिंग दी गई है:

ए, "स्ट्रिंग, साथ", विभिन्न, "मान, और कुछ", उद्धृत

उद्धृत वर्गों के अंदर अल्पविरामों को अनदेखा करते समय इसे अल्पविरामों के आधार पर विभाजित करने के लिए एक अच्छा एल्गोरिदम क्या है?

आउटपुट एक सरणी होना चाहिए:

["a", "string, with", "विभिन्न", "मान, और कुछ", "उद्धृत"]

0
ro fr bn
यदि मूल स्ट्रिंग में उद्धरणों की एक विषम संख्या दिखाई देती है तो क्या होगा?
जोड़ा लेखक Brock D, स्रोत
यह एक अनुचित उद्धृत इनपुट स्ट्रिंग का संकेत देगा, इसलिए एक अपवाद फेंकना एक विकल्प होगा।
जोड़ा लेखक J c, स्रोत

12 उत्तर

अजगर:

import csv
reader = csv.reader(open("some.csv"))
for row in reader:
    print row
0
जोड़ा
मैं इसे सबसे अच्छा जवाब मानता हूं। वही है जो मुझे चाहिए!
जोड़ा लेखक Alex. S., स्रोत

यदि उद्धरणों की एक विषम संख्या दिखाई देती है तो क्या होगा   मूल स्ट्रिंग में?

यह सीएसवी पार्सिंग की तरह बेहद दिखता है, जिसमें उद्धृत क्षेत्रों को संभालने के लिए कुछ विशिष्टताएं हैं। फ़ील्ड केवल बच निकला है यदि फ़ील्ड को डबल कोटेशन के साथ सीमित किया गया है, इसलिए:

field1, "field2, field3", field4, "field5, field6" field7

हो जाता है

फ़ील्ड 1

     

field2, field3

     

फ़ील्ड 4

     

"फ़ील्ड 5

     

field6 "field7

ध्यान दें कि अगर यह दोनों उद्धरण के साथ शुरू और समाप्त नहीं होता है, तो यह उद्धृत फ़ील्ड नहीं है और डबल कोट्स को डबल कोट्स के रूप में माना जाता है।

निस्संदेह मेरा कोड जो किसी से जुड़ा हुआ है, वास्तव में इसे सही तरीके से संभाल नहीं लेता है, अगर मुझे सही याद है।

0
जोड़ा

बेशक एक सीएसवी पार्सर का उपयोग करना बेहतर है लेकिन सिर्फ इसके मजाक के लिए आप यह कर सकते हैं:

Loop on the string letter by letter.
    If current_letter == quote : 
        toggle inside_quote variable.
    Else if (current_letter ==comma and not inside_quote) : 
        push current_word into array and clear current_word.
    Else 
        append the current_letter to current_word
When the loop is done push the current_word into array 
0
जोड़ा

यहां एक सरल एल्गोरिदम है:

  1. Determine if the string begins with a '"' character
  2. Split the string into an array delimited by the '"' character.
  3. Mark the quoted commas with a placeholder #COMMA#
    • If the input starts with a '"', mark those items in the array where the index % 2 == 0
    • Otherwise mark those items in the array where the index % 2 == 1
  4. Concatenate the items in the array to form a modified input string.
  5. Split the string into an array delimited by the ',' character.
  6. Replace all instances in the array of #COMMA# placeholders with the ',' character.
  7. The array is your output.

पाइथन कार्यान्वयन है:
('ए, बी ", सी," डी, ई, एफ, एच "," आई, जे, के "को संभालने के लिए तय किया गया है)

def parse_input(input):

    quote_mod = int(not input.startswith('"'))

    input = input.split('"')
    for item in input:
        if item == '':
            input.remove(item)
    for i in range(len(input)):
        if i % 2 == quoted_mod:
            input[i] = input[i].replace(",", "#COMMA#")

    input = "".join(input).split(",")
    for item in input:
        if item == '':
            input.remove(item)
    for i in range(len(input)):
        input[i] = input[i].replace("#COMMA#", ",")
    return input

# parse_input('a,"string, with",various,"values, and some",quoted')
#  -> ['a,string', ' with,various,values', ' and some,quoted']
# parse_input('"a,b",c,"d,e,f,h","i,j,k"')
#  -> ['a,b', 'c', 'd,e,f,h', 'i,j,k']
0
जोड़ा

मैं तारों को पार्स करने के लिए इसका उपयोग करता हूं, यह सुनिश्चित नहीं करता कि यह यहां मदद करता है; लेकिन शायद कुछ मामूली संशोधन के साथ?

function getstringbetween($string, $start, $end){
    $string = " ".$string;
    $ini = strpos($string,$start);
    if ($ini == 0) return "";
    $ini += strlen($start);   
    $len = strpos($string,$end,$ini) - $ini;
    return substr($string,$ini,$len);
}

$fullstring = "this is my [tag]dog[/tag]";
$parsed = getstringbetween($fullstring, "[tag]", "[/tag]");

echo $parsed; // (result = dog) 

/एमपी

0
जोड़ा

मैं यह देखने के लिए विरोध नहीं कर सका कि क्या मैं इसे पायथन एक-लाइनर में काम कर सकता हूं:

arr = [i.replace("|", ",") for i in re.sub('"([^"]*)\,([^"]*)"',"\g<1>|\g<2>", str_to_test).split(",")]

रिटर्न ['ए', 'स्ट्रिंग,', 'विभिन्न', 'मान, और कुछ', 'उद्धृत']

यह पहले उद्धरण के अंदर ',' को दूसरे विभाजक (|) में बदलकर काम करता है, ',' पर स्ट्रिंग को विभाजित करना और | विभाजक फिर से।

0
जोड़ा
आप कैसे जानते हैं कि कोई नहीं है मूल स्ट्रिंग में? उद्धृत तारों के अंदर उद्धरण से बचने के बारे में क्या?
जोड़ा लेखक MarkJ, स्रोत

यह एक मानक सीएसवी-शैली पार्स है। बहुत से लोग नियमित अभिव्यक्तियों के साथ ऐसा करने की कोशिश करते हैं। आप regexes के साथ लगभग 9 0% प्राप्त कर सकते हैं, लेकिन आपको इसे सही तरीके से करने के लिए वास्तव में एक वास्तविक सीएसवी पार्सर की आवश्यकता है। मुझे कुछ महीने पहले एक कोडप्रोजेक्ट पर तेज़, उत्कृष्ट सी # सीएसवी पार्सर मिला था मै इसकी अत्यधिक सिफारिश करता हु!

0
जोड़ा
धन्यवाद! सी # लड़के के रूप में, मैं हमेशा भूल जाता हूं कि वहां उपयोगी वीबी पुस्तकालयों का एक गुच्छा है जिसका उपयोग मैं कर सकता हूं। ईमानदारी से, मुझे लगता है कि वे खराब नाम हैं, क्योंकि वे वास्तव में वीबी नहीं हैं। वे सिर्फ .NET हैं।
जोड़ा लेखक Simon Gillbee, स्रोत
पाठ्यक्रम के .NET ढांचे में भी एक है। भले ही यह माइक्रोसॉफ्ट में है। VisualBasic आप अभी भी इसे सी # से उपयोग कर सकते हैं। msdn.microsoft.com/en-us/library/ & hellip;
जोड़ा लेखक MarkJ, स्रोत

अगर मेरी पसंद की भाषा बिना सोच के ऐसा करने का कोई तरीका नहीं देती है तो मैं शुरुआत में दो विकल्पों को आसान तरीके से मानता हूं:

  1. प्री-पार्स और किसी अन्य नियंत्रण चरित्र के साथ स्ट्रिंग के भीतर अल्पविराम को प्रतिस्थापित करें, फिर उन्हें विभाजित करें, उसके बाद पहले से कॉमा के साथ उपयोग किए गए नियंत्रण वर्ण को प्रतिस्थापित करने के लिए सरणी पर पोस्ट-पार्स के बाद।

  2. वैकल्पिक रूप से उन्हें अल्पविरामों पर विभाजित करें, जिसके परिणामस्वरूप सरणी को प्रत्येक सरणी प्रविष्टि पर अग्रणी उद्धरणों के लिए एक और सरणी जांच में पोस्ट करें और जब तक मैं एक समाप्ति उद्धरण तक नहीं पहुंच जाता तब तक प्रविष्टियों को जोड़ना।

हालांकि ये हैक्स हैं, और यदि यह एक शुद्ध 'मानसिक' अभ्यास है तो मुझे संदेह है कि वे अनुपयोगी साबित होंगे। यदि यह वास्तविक दुनिया की समस्या है तो यह भाषा को जानने में मदद करेगा ताकि हम कुछ विशिष्ट सलाह दे सकें।

0
जोड़ा
मैं एक समान समस्या के लिए एक एल्गोरिदम खोज रहा हूं जहां मुझे बड़ी टेक्स्ट फ़ाइलों (जीबी में) को संसाधित करना है। इन पाठ फ़ाइलों में योग्य डेटा होता है यानी फ़ील्ड / रिकॉर्ड डेलीमीटर डेटा का हिस्सा होता है जब सिंगल / डबल कोट द्वारा संलग्न होता है। मैं एल्गोरिदम की तलाश में हूं जो मुझे इन फ़ाइलों को समानांतर (एकाधिक धागे से) में संसाधित करने में मदद कर सकता है। हम जिस भाषा का उपयोग करते हैं वह जावा है। मुझे पता है यदि आप किसी को भी सुझाव देते है
जोड़ा लेखक Andy Dufresne, स्रोत

यहां लेखक ने सी # कोड के एक ब्लॉब में गिरा दिया जो उस परिदृश्य को संभालता है जिसमें आपको कोई समस्या है:

.NET में CSV फ़ाइल आयात

अनुवाद करना बहुत मुश्किल नहीं होना चाहिए।

0
जोड़ा

ऐसा लगता है कि आपके यहां कुछ अच्छे उत्तर हैं।

आप में से उन लोगों के लिए जो आपकी स्वयं की सीएसवी फ़ाइल पार्सिंग को संभालने की तलाश में हैं, विशेषज्ञों की सलाह पर ध्यान दें और अपना स्वयं का सीएसवी रोल न करें पार्सर

Your first thought is, "I need to handle commas inside of quotes."

Your next thought will be, "Oh, crap, I need to handle quotes inside of quotes. Escaped quotes. Double quotes. Single quotes..."

यह पागलपन के लिए एक सड़क है। अपना खुद का मत लिखो। एक विस्तृत यूनिट परीक्षण कवरेज वाली लाइब्रेरी खोजें जो सभी हार्ड पार्ट्स को हिट करती है और आपके लिए नरक से गुज़र चुकी है। .NET के लिए, नि: शुल्क FileHelpers लाइब्रेरी का उपयोग करें।

0
जोड़ा
गुप्तजीक पर एक महान लिंक - बहुत मनोरंजक। लेकिन यह केवल .NET का उपयोग करने वाले लोगों के लिए प्रश्न का उत्तर देता है।
जोड़ा लेखक Magnus Smith, स्रोत
सच; हालांकि सलाह हर जगह देवताओं पर लागू होती है: अपने स्वयं के सीएसवी पार्सर की भूमिका निभाएं। रूबी में एक अंतर्निर्मित है, और वहां पाइथन, सी ++ के लिए लाइब्रेरी हैं, जो कि किसी भी व्यापक रूप से उपयोग की जाने वाली भाषा है।
जोड़ा लेखक Judah Himango, स्रोत
+10 अगर यह मुझे दे देगा :)
जोड़ा लेखक MarkJ, स्रोत
और हालांकि SecretGeek इसे नहीं जानता है, वहीं भी एक VB.NET में बनाया गया है। msdn.microsoft.com/en-us/library/ & hellip;
जोड़ा लेखक MarkJ, स्रोत

एक पास में एक स्यूडोकोड (ए.के.ए. पायथन) में एक है :- पी

def parsecsv(instr):
    i = 0
    j = 0

    outstrs = []

    # i is fixed until a match occurs, then it advances
    # up to j. j inches forward each time through:

    while i < len(instr):

        if j < len(instr) and instr[j] == '"':
            # skip the opening quote...
            j += 1
            # then iterate until we find a closing quote.
            while instr[j] != '"':
                j += 1
                if j == len(instr):
                    raise Exception("Unmatched double quote at end of input.")

        if j == len(instr) or instr[j] == ',':
            s = instr[i:j]  # get the substring we've found
            s = s.strip()    # remove extra whitespace

            # remove surrounding quotes if they're there
            if len(s) > 2 and s[0] == '"' and s[-1] == '"':
                s = s[1:-1]

            # add it to the result
            outstrs.append(s)

            # skip over the comma, move i up (to where
            # j will be at the end of the iteration)
            i = j+1

        j = j+1

    return outstrs

def testcase(instr, expected):
    outstr = parsecsv(instr)
    print outstr
    assert expected == outstr

# Doesn't handle things like '1, 2, "a, b, c" d, 2' or
# escaped quotes, but those can be added pretty easily.

testcase('a, b, "1, 2, 3", c', ['a', 'b', '1, 2, 3', 'c'])
testcase('a,b,"1, 2, 3" , c', ['a', 'b', '1, 2, 3', 'c'])

# odd number of quotes gives a "unmatched quote" exception
#testcase('a,b,"1, 2, 3" , "c', ['a', 'b', '1, 2, 3', 'c'])
0
जोड़ा

पैट के छद्म कोड के आधार पर यहां एक साधारण पायथन कार्यान्वयन है:

def splitIgnoringSingleQuote(string, split_char, remove_quotes=False):
    string_split = []
    current_word = ""
    inside_quote = False
    for letter in string:
      if letter == "'":
        if not remove_quotes:
           current_word += letter
        if inside_quote:
          inside_quote = False
        else:
          inside_quote = True
      elif letter == split_char and not inside_quote:
        string_split.append(current_word)
        current_word = ""
      else:
        current_word += letter
    string_split.append(current_word)
    return string_split
0
जोड़ा