【问题标题】:Divide two String into substrings and pair them将两个字符串分成子字符串并配对
【发布时间】:2016-12-08 20:59:48
【问题描述】:

我正在为这个问题寻找有趣的解决方案:

String key = "1;2;3;4";
String value = "Value1;Value2;Value whitespace;"

现在';'将每个值与另一个值分开。相同的符号'​​;'也分配密钥。

现在我想结束:

{"1" : "Value1", "2" : "Value2", "3" : "Value whitespace", "4" : null}

当然,如果值比键多,那么 null 不应该是该对的左侧(null:“Value5”)。

我使用 char 数组为这个问题做了一个非常复杂的解决方案,但它是一个包含许多案例和东西的大型 FOR。(它是 O(n))。所以我很想看到一个正则表达式或子字符串解决方案或不包含大循环的东西。

编辑: 我的解决方案:

private List<ExampleObject> getExampleObjects(String key , String value) {
    // s
    if (key  == null || value == null) {
        return new ArrayList<ExampleObject>();
    }

    List<ExampleObject> exampleObjects = new ArrayList<ExampleObject>();

    char[] keyToCharArray = key.toCharArray();
    char[] valueToCharArray = value.toCharArray();

    StringBuilder name = new StringBuilder();
    StringBuilder value = new StringBuilder();

    boolean nameCompleted = false;
    boolean valueCompleted = false;

    for (int i = 0, j = 0; i < keyToCharArray.length || j < valueToCharArray.length;) {
        if (!nameCompleted) {
            char a = ' ';
            try{
                 a = keyToCharArray[i];
            } catch(Exception e){
                 a = ';';
                // throw : VALES and key  not match. More key  then value
                //throw(e);
            }

            if (a == ';' ) {
                nameCompleted = true;
            } else if (!(i + 1 < keyToCharArray.length)){
                name.append(a);
                nameCompleted = true;
            }   else {
                name.append(a);

            }
            i++;
        }
        if (!valueCompleted) {

            char a = ' ';
            try{
                 a = valueToCharArray[j];
            } catch(Exception e){
                 a = ';';
                // throw : VALES and key  not match. More value then key 
                //throw(e);
            }

            if (a == ';') {
                valueCompleted = true;
            } else if(!(j + 1 < valueToCharArray.length)) {
                value.append(a);
                valueCompleted = true;
            } else {
                value.append(a);
            }
            j++;
        }
        if (nameCompleted && valueCompleted) {
            exampleObjects.add(new ExampleObject(name.toString(), value.toString()));
            name.setLength(0);
            value.setLength(0);
            nameCompleted = false;
            valueCompleted = false;
        }
    }
    return exampleObjects;
}

其中 ExampleObject.class 有字段 keyvalue

【问题讨论】:

  • 抱歉,我们希望您提供一些代码;不仅是要求。你知道,写一个使用 indexOf 和 substring 操作的 for 循环不会太难;或者干脆分开;也应该很好用。
  • 你希望这到底是什么数据结构?如果您有多个映射到null 的值,则它不是Map。一般来说,这只是拆分字符串并循环遍历结果数组的问题,但这取决于您希望获得的结果。
  • 井地图本来可以的。我对正则表达式更好奇,因为我不擅长编写包括正则表达式在内的解决方案,所以只是想看看它会是什么样子。
  • 我不相信没有某种循环就可以做到这一点。但如果事实证明它可能的,那么它只能是最复杂和最讨厌的代码。我不禁想到这个问题会更适合编程代码高尔夫网站。
  • 好的,看来您的源代码会创建一个配对列表。这是一个合法的选择。你知道String中的split方法吗?

标签: java string dictionary substring


【解决方案1】:

另一个 - 稍微更优雅的 Java8 和 Generic。

/**
 * General pair of items.
 *
 * @param <P> - Type of the first item in the pair.
 * @param <Q> - Type of the second item.
 */
static class Pair<P, Q> {
    final P p;
    final Q q;

    public Pair(P p, Q q) {
        this.p = p;
        this.q = q;
    }

    @Override
    public String toString() {
        return "{" + p + "," + q + "}";
    }
}

/**
 * Gets the `n`th item is present in the array - otherwise returns null.
 *
 * @param a   - The array
 * @param n   - Which one in the array we want.
 * @param <T> - The type of the array entries.
 * @return - The `n`th entry in the array or null if not present.
 */
private static <T> T n(T[] a, int n) {
    return n < a.length ? a[n] : null;
}

/**
 * Pairs up each element in the arrays.
 *
 * @param <P> - The type of the elements in the `P` array.
 * @param <Q> - The type of the elements in the `Q` array.
 * @param ps  - The `P` array.
 * @param qs  - The `Q` array.
 * @return A list of `Pair`s of each element.
 */
static <P, Q> List pairUp(P[] ps, Q[] qs) {
    return IntStream.range(0, Math.max(ps.length, qs.length))
            .mapToObj(i -> new Pair<>(n(ps, i), n(qs, i)))
            .collect(Collectors.toList());
}

/**
 * Splits the two strings on a separator and returns a list of Pairs of the corresponding items.
 *
 * @param a         - The first string.
 * @param b         - The second string.
 * @param separator - The separator.
 * @return - A List of Paired up entries from `a` and `b`.
 */
private static List<Pair<String, String>> fold(String a, String b, String separator) {
    return pairUp(a.split(separator, -1), b.split(separator, -1));
}

public void test() {
    System.out.println(fold("1;2;3;4", "Value1;Value2;Value whitespace", ";"));
}

【讨论】:

  • 不错!看起来合法
【解决方案2】:

另一种观点:不要“手动”做这些事情。

我的意思是:不要自己做所有“低级”操作;你应该抽象。

首先,将您的键值字符串转换为Map。喜欢:

String keys[] = keyString.split(";");
String values[] = valueString.split(";);

... probably some consistency checks that arrays have same length; and  no nulls in keys

Map<String, String> map = new HashMap<>();
for (int i=0; i < keys.length; i++) {
  map.put(keys[i], values[i]);
}

最后,使用一些现有的 JSON 库来简单地基于该映射生成 JSON 表示。

换句话说:除非您谈论的是包含数百万条目的列表;不用担心性能。相反,要担心好的抽象,而不是重新发明轮子和代码的可读性。

但如果您真的需要担心性能或内存方面的问题,那么只需拆分为数组,然后将这两个数组用作某个函数的输入,该函数使用 StringBuilder 构建所需的输出字符串。

【讨论】:

    【解决方案3】:

    Java 8:

    String key = "1;2;3;4";
    String value = "Value1;Value2;Value whitespace;";
    String[] keys = key.split(";", -2);
    String[] values = value.split(";", -2);
    
    Map<String, String> result = IntStream.range(0, keys.length).mapToObj(i->i).collect(Collectors.toMap(i->keys[i], i-> values[i]));
    result.entrySet().forEach(e->result.put(e.getKey(), e.getValue().length()==0 ? null : e.getValue()));
    

    【讨论】:

      【解决方案4】:

      我想出了解决您问题的方法:

      输出

      {"1" : "Value1", "2" : "Value2", "3" : "Value whitespace", "4" : "null"}       
      

      代码

      public class HelloWorld{
      
           public static void main(String []args){
              String key = "1;2;3;4";
              String value = "Value1;Value2;Value whitespace;";
      
              String[] keyArr = key.split(";");
              String[] valueArr = value.split(";");
      
              String finalJSON = "{";
              for(int i=0; i<(keyArr.length > valueArr.length ? keyArr.length : valueArr.length); i++) {
      
                  try {
                      finalJSON += "\"" + keyArr[i] + "\"";
                  }
                  catch(ArrayIndexOutOfBoundsException e) {
                      finalJSON += "\"null\"";
                  }
      
                  finalJSON += " : ";
      
                  try {
                      finalJSON += "\"" + valueArr[i] + "\"";
                  }
                  catch(ArrayIndexOutOfBoundsException e) {
                      finalJSON += "\"null\"";
                  }
                  if(i!=(keyArr.length > valueArr.length ? keyArr.length : valueArr.length) - 1) 
                      finalJSON += ", ";
              }
              finalJSON += "}";
      
              System.out.println(finalJSON);
           }
      }
      

      【讨论】:

        【解决方案5】:

        尝试以下操作:(如果您想按您所说的打印字符串)

        1. 使用String#split()将两个字符串拆分成数组
        2. value[]key[] 创建计数器
        3. 创建boolean 以指示是否附加了键或值
        4. 使用StringBuilder并循环遍历key[]的长度
        5. 追加内容
        6. 使用StringBuilder#append() 返回一个新的String

        完成。在查看解决方案之前先尝试一下!

        字符串生成器:https://docs.oracle.com/javase/7/docs/api/java/lang/StringBuilder.html
        字符串:https://docs.oracle.com/javase/7/docs/api/java/lang/String.html

        我打印字符串的解决方案:

        public static void main(String[] args) {
            String key = "1;2;3;4";
            String value = "Value1;Value2;Value whitespace";
        
            String[] keys = key.split(";");
            String[] values = value.split(";");
        
            StringBuilder sb = new StringBuilder("{");
            boolean isKey = true;
            int keyCount = 0;
            int valueCount = 0;
        
            for(int i = 0; i < key.length(); i++) {
                sb.append("\"");
        
                if(isKey) {
                    sb.append(keys[keyCount]).append("\" : ");
                    keyCount++;
                } else {
                    sb.append(values[valueCount]).append("\", ");
                    valueCount++;
                }
                isKey = !isKey;
            }
        
            sb.append("}");
            System.out.println(sb.toString());
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-05-22
          • 1970-01-01
          • 2013-03-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多