鉴于一串这样的:

一个,"string,"、各种"价值观,以及一些",引述

什么是一个很好的算法来分裂这个基础上逗号,而忽略的逗号内所引用的部分?

输出应该是一阵列:

["a","string,"、"各种","的价值观,以及一些","援引"]

有帮助吗?

解决方案

如果我选择的语言没有提供一种方法来这样做不经思考然后我想最初考虑的两个选项作出的最容易的方法:

  1. 预先分析和替代逗号内的字符串的另一个控制符,然后将它们分开,然后由后分析上列代替控制的性格中使用前面的逗号。

  2. 或者分裂他们的逗号,然后分析得到的数组成的另一个阵列检查对于领先报价的每个阵列进入和连接的项目,直到我到达终报价。

这些都是黑客但是,如果这是一个纯粹的'精神'的锻炼那么我怀疑他们将证明是无益的。如果这是真实世界的问题,那么它会有助于了解的语言,所以,我们可以提供一些具体的建议。

其他提示

看起来你已经有了一些很好的答案在这里。

对于那些希望处理自己的CSV文件的分析,听取专家的意见和 不滚你自己CSV分析器.

你首先想到的是, "我需要处理逗号内的报价。"

你下一步想到会, "哦,该死,我需要处理的报价内部的报价。逃脱的报价。双引号。单一的报价..."

这是一个道路的疯狂。不要写你自己。找到一个图书馆与一个广泛的单元测试的复盖范围,所有硬件和具有经历过地狱给你。为。网,使用免费的 FileHelpers 图书馆。

蟒蛇:

import csv
reader = csv.reader(open("some.csv"))
for row in reader:
    print row

当然使用计分析程序是更好,但只是为了好玩的你可以:

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 

提交人在这里下降了在blob C#代码处理这一情况你有一个问题:

CSV文件的进口。净

应该不会太难以翻译。

如果有什么奇数的报价出现 在原来的字符串?

这看起来喜欢惊人地CSV分析,其中有一些特殊性,以处理援引的领域。该领域是唯一逃出,如果领域界定的双语录,所以:

field1,"field2,field3",字段4,"field5,field6"field7

变得

field1

field2,field3

字段4

"field5

field6"field7

通知如果它不这两个的开始和结束有报价,那么它不是一个引述的领域和双引号是简单地视为双引号。

Insedently我的代码,有人联系实际上并不处理这个正确,如果我记忆正确的。

这里有一个简单的python执行情况的基础上拍的伪:

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

我用这个分析串,不知道如果它有助于在这里;但有一些小的修改吗?

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) 

/mp

这是一个标准的CSV式的分析。很多人尝试这样做与正常的表达。你可以得到约90%,与regex,但你真的需要一个真正的CSV分析器来做正确。我发现了一个 快速、优秀C#CSV分析器上演示 几个月前,我强烈推荐!

这里有一个在伪(a。k.a.蟒)在一个通过:-P

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'])

这里有一个简单的算法:

  1. 确定如果串的开始 '"' 字符
  2. 分串入一系列分隔 '"' 符。
  3. 标记的报逗号有一个占位 #COMMA#
    • 如果输入的开始 '"', mark这些项目中的阵列的索引%2==0
    • 无标记的那些项目中的阵列的索引%2==1
  4. 串联项目中的阵列,以形成一个修改输入串。
  5. 分串入一系列分隔 ',' 符。
  6. 代替所有实例中的阵列的 #COMMA# 占位与 ',' 符。
  7. 阵列是你的输出。

这里是蟒蛇的执行情况:
(固定来处理'"a、b"、c、"d、e、f、h","i,j,k"')

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']

我只是忍不住看如果我能让它工作中的蟒蛇之一衬:

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

返回['a'、'string,','的各种','值,和一些','引用']

它的工作通过首先取代','内部报价,另一个分离器(|), 分裂的串上'、'以及更换|分离。

由于你所说的语言无关,我写了我的算法中的语言是最接近伪为posible:

def find_character_indices(s, ch):
    return [i for i, ltr in enumerate(s) if ltr == ch]


def split_text_preserving_quotes(content, include_quotes=False):
    quote_indices = find_character_indices(content, '"')

    output = content[:quote_indices[0]].split()

    for i in range(1, len(quote_indices)):
        if i % 2 == 1: # end of quoted sequence
            start = quote_indices[i - 1]
            end = quote_indices[i] + 1
            output.extend([content[start:end]])

        else:
            start = quote_indices[i - 1] + 1
            end = quote_indices[i]
            split_section = content[start:end].split()
            output.extend(split_section)

        output += content[quote_indices[-1] + 1:].split()                                                                 

    return output
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top