【问题标题】:Split string in square brackets from Google translator从谷歌翻译器中拆分方括号中的字符串
【发布时间】:2016-08-24 21:25:29
【问题描述】:

我从 Google 语言翻译服务接收数据,需要帮助拆分数据。

void Start()
{
    translateText("Hello, This is a test!", "en", "fr");
}

void translateText(string text, string fromLanguage, string toLanguage)
{
    string url = "https://translate.googleapis.com/translate_a/single?client=gtx&sl=" + fromLanguage + "&tl=" + toLanguage + "&dt=t&q=" + Uri.EscapeUriString(text);
    StartCoroutine(startTranslator(url));
}

IEnumerator startTranslator(string url)
{
    UnityWebRequest www = UnityWebRequest.Get(url);
    yield return www.Send();

    Debug.Log("Raw string Received: " + www.downloadHandler.text);

    LanguageResult tempResult = decodeResult(www.downloadHandler.text);

    Debug.Log("Original Text: " + tempResult.originalText);
    Debug.Log("Translated Text: " + tempResult.translatedText);
    Debug.Log("LanguageIso: " + tempResult.languageIso);

    yield return null;
}

LanguageResult decodeResult(string result)
{
    char[] delims = { '[', '\"', ']', ',' };
    string[] arr = result.Split(delims, StringSplitOptions.RemoveEmptyEntries);

    LanguageResult tempLang = null;
    if (arr.Length >= 4)
    {
        tempLang = new LanguageResult();
        tempLang.translatedText = arr[0];
        tempLang.originalText = arr[1];
        tempLang.unknowValue = arr[2];
        tempLang.languageIso = arr[3];
    }
    return tempLang;
}

public class LanguageResult
{
    public string translatedText;
    public string originalText;
    public string unknowValue;
    public string languageIso;
}

然后使用Start() 函数中的translateText("Hello, This is a test!", "en", "fr"); 调用它,该函数使用ISO 639-1 Code 将英语句子转换为法语。

接收到的数据如下所示:

[[["Bonjour, Ceci est un test!","Hello, This is a test!",,,0]],,"en"]

我想这样拆分:

  • 你好,Ceci est un test!
  • 你好,这是一个测试!
  • 0
  • zh

并将它们按顺序放入一个字符串数组中。

我目前使用这个:

char[] delims = { '[', '\"', ']', ',' };
        string[] arr = result.Split(delims, StringSplitOptions.RemoveEmptyEntries);

如果接收到的字符串中没有逗号,则此方法有效。如果有逗号,则拆分的值会混乱。最好的分割方法是什么?

编辑

使用Blorgbeard's 解决方案,最终的工作代码如下。希望这会对其他人有所帮助。此不应用于商业目的,而应用于个人或学校项目。

void Start()
{
    //translateText("Hello, This is \" / \\ a test !", "en", "fr");
    //translateText("Hello, This is , \\ \" a test !", "en", "fr");
    translateText("Hello, This is a test!", "en", "fr");
}

void translateText(string text, string fromLanguage, string toLanguage)
{
    string url = "https://translate.googleapis.com/translate_a/single?client=gtx&sl=" + fromLanguage + "&tl=" + toLanguage + "&dt=t&q=" + Uri.EscapeUriString(text);
    StartCoroutine(startTranslator(url));
}

IEnumerator startTranslator(string url)
{
    UnityWebRequest www = UnityWebRequest.Get(url);
    yield return www.Send();

    Debug.Log("Raw string Received: " + www.downloadHandler.text);

    LanguageResult tempResult = decodeResult(www.downloadHandler.text);
    displayResult(tempResult);
    yield return null;
}

void displayResult(LanguageResult translationResult)
{
    Debug.Log("Original Text: " + translationResult.originalText);
    Debug.Log("Translated Text: " + translationResult.translatedText);
    Debug.Log("LanguageIso: " + translationResult.languageIso);
}

LanguageResult decodeResult(string result)
{
    string[] arr = Decode(result);

    LanguageResult tempLang = null;
    if (arr.Length >= 4)
    {
        tempLang = new LanguageResult();
        tempLang.translatedText = arr[0];
        tempLang.originalText = arr[1];
        tempLang.unknowValue = arr[2];
        tempLang.languageIso = arr[3];
    }
    return tempLang;
}

public class LanguageResult
{
    public string translatedText;
    public string originalText;
    public string unknowValue;
    public string languageIso;
}

private string[] Decode(string input)
{
    List<string> finalResult = new List<string>();

    bool inToken = false;
    bool inString = false;
    bool escaped = false;
    var seps = ",[]\"".ToArray();
    var current = "";
    foreach (var chr in input)
    {
        if (!inString && chr == '"')
        {
            current = "";
            inString = true;
            continue;
        }
        if (inString && !escaped && chr == '"')
        {
            finalResult.Add(current);
            current = "";
            inString = false;
            continue;
        }
        if (inString && !escaped && chr == '\\')
        {
            escaped = true;
            continue;
        }
        if (inString && (chr != '"' || escaped))
        {
            escaped = false;
            current += chr;
            continue;
        }
        if (inToken && seps.Contains(chr))
        {
            finalResult.Add(current);
            current = "";
            inToken = false;
            continue;
        }
        if (!inString && chr == '"')
        {
            inString = true;
            current = "";
            continue;
        }
        if (!inToken && !seps.Contains(chr))
        {
            inToken = true;
            current = "";
        }
        current += chr;
    }
    return finalResult.ToArray();
}

【问题讨论】:

  • 字符串中是否也可以包含(转义)引号?
  • @Blorgbeard 我刚刚检查过,是的,它可以有 \" 。这对我来说太棘手了。
  • @l'L'l 如果你能提供一个例子就好了。
  • 几乎 JSON,你也许能找到处理空数组元素的JSON解析器。

标签: c# unity3d split


【解决方案1】:

您可以自己编写一个简单的解析器。这是我拼凑在一起的一个(可以进行一些清理,但演示了这个想法):

private static IEnumerable<string> Parse(string input) {
    bool inToken = false;
    bool inString = false;
    bool escaped = false;
    var seps = ",[]\"".ToArray();
    var current = "";
    foreach (var chr in input) {
        if (!inString && chr == '"') {
            current = "";
            inString = true;
            continue;
        }
        if (inString && !escaped && chr == '"') {
            yield return current;
            current = "";
            inString = false;
            continue;
        }
        if (inString && !escaped && chr == '\\') {
            escaped = true;
            continue;
        }
        if (inString && (chr != '"' || escaped)) {
            escaped = false;
            current += chr;
            continue;
        }
        if (inToken && seps.Contains(chr)) {
            yield return current;
            current = "";
            inToken = false;
            continue;
        }
        if (!inString && chr == '"') {
            inString = true;
            current = "";
            continue;
        }
        if (!inToken && !seps.Contains(chr)) {
            inToken = true;
            current = "";
        }
        current += chr;
    }
}

这是jsfiddle demo

【讨论】:

  • 开箱即用的想法在这里+1
  • 是否可以将其变成一个返回包含这些结果的 4 字符串数组的函数?所以不是private static IEnumerable&lt;string&gt; Parse(string input),而是private string [] Parse(string input)?
  • 当然,只需将其包装并调用.ToArray() - 或者您可以添加到List&lt;string&gt; 而不是yield returning 值,然后在最后返回列表.ToArray()ed。
  • 我做了类似this 之类的操作,但没有奏效。你能发现问题吗?
  • 是的,finalResult.Add(current); 应该在我有yield return current 的地方,而不仅仅是在底部。
【解决方案2】:

使用Regex.Split 你可以做这样的事情,例如:

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
        var input ="[[[\"Bonjour, Ceci est un test!\",\"Hello, This is a test!\",,,0]],,\"en\"]";
        var parse = Regex.Split(input, "\\[|\\]|[^a-zA-Z ],|\",\"|\"|\"");
        foreach(var item in parse) {
            bool result = !String.IsNullOrEmpty(item) && (Char.IsLetter(item[0]) || Char.IsDigit(item[0]));
            if (result) {
                Console.WriteLine(item);
            }
        }
   }
}

输出:

Bonjour, Ceci est un test!
Hello, This is a test!
0
en

如果您想要拆分的所有内容,您可以简单地删除 bool 检查字母字符。

【讨论】:

  • 哇,这太接近了。唯一的问题是它跳过了0。请再看一遍这个问题。你会看到哪个0
  • 还是和你原来的答案一样。
  • @Programmer:见编辑(在线示例:dotnetfiddle.net/00jsNa
  • 我不知道为什么,但是没有0,我得到了相同的结果。
  • 不客气!正则表达式有时需要对像您这样的更复杂的场景进行大量修改,但无论如何很高兴您找到了解决方案。
【解决方案3】:

这是一个疯狂的想法 - 由 " 拆分,然后由其余部分拆分(但如果在 " 之间存在 ",则不会工作)

var s = @"[[[""Bonjour, Ceci est un test!"",""Hello, This is a test!"",,,0]],,""en""]";

var a = s.Split('"').Select((x, i) => (i & 1) > 0 ? new[] { x } : x.Split("[],".ToArray(),  
                     StringSplitOptions.RemoveEmptyEntries)).SelectMany(x => x).ToArray();

Debug.Print(string.Join("|", a)); // "Bonjour, Ceci est un test!|Hello, This is a test!|0|en"

【讨论】:

  • 有效,但当其中有转义引号时失败。谢谢你的回答。
【解决方案4】:

您可以尝试使用正则表达式进行拆分。我用你提供的样品进行了测试。结果是这样的。

    var str="[[[\"Bonjour, Ceci est un test!\",\"Hello, This is a test!\",,,0]],,\"en\"]";
    var splitted=Regex.Split(str,@"\[|\]|\,");
    foreach(var split in splitted){
       Console.WriteLine(split );
    }

   "Bonjour Ceci est un test!"
   "Hello This is a test!"
    0
   "en"

【讨论】:

  • 这不起作用,长度是 15 而不是 4。我在数组 [3] 中得到了 "Bonjour
猜你喜欢
  • 2015-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-03
  • 1970-01-01
  • 1970-01-01
  • 2019-08-26
相关资源
最近更新 更多