一亩三分地论坛

 找回密码
 获取更多干货,去instant注册!

扫码关注一亩三分地公众号
查看: 1022|回复: 5
收起左侧

[算法题] 求教一道算法题, parse json

[复制链接] |试试Instant~ |关注本帖
pinkdatura 发表于 2016-8-24 04:41:38 | 显示全部楼层 |阅读模式

注册一亩三分地论坛,查看更多干货!

您需要 登录 才可以下载或查看,没有帐号?获取更多干货,去instant注册!

x

就是给个string,按格式打印json,注意缩进和换行
http://jsonprettyprint.com/
类似这种的, 输入[1,2,3, {"id": 1, "name": "wang", "tag":[1,"home",2], "price":234}]
要求打出来这个
[  
   1,  
   2,  
   3,  
  {   
     "id": 1,   
     "name": "wang",   
     "tag": [      1,      "home",      2    ],   
     "price": 234
   }
]
stellari 发表于 2016-8-24 15:37:07 | 显示全部楼层
pinkdatura 发表于 2016-8-24 04:43
我的做法是iterative的,可是面试还是fail了,脸家店面,所以求教

代码基本意思有了,不过略微繁琐了些,而且某些地方和jsonprettyprint.com的结果有点出入。比如你的代码里{和[前都有换行,而jsonprettyprint中则是没有的。观察jsonprettyprint能推出真正导致换行的只有两种情况:1. {[,之后;2. ]}之前。另外的规则是1. {的下一行indent比本行增加; 2. }所在的那一行indent比上一行减少。3. 只有在换行出现以后才输出indent的空格。
只要把上面这些情况综合在一起即可。我大概写了些,交流一下。
  1.   public static void prettyJSON(String s) {
  2.     int indent=0;
  3.     boolean lastLineBreak = false; // If the last char results in linebreak
  4.     for (int i = 0; i < s.length(); i++) {
  5.       boolean isEnd = (s.charAt(i)==']' || s.charAt(i)=='}');
  6.       boolean isBegin = (s.charAt(i)=='[' || s.charAt(i)=='{');
  7.       boolean isComma = s.charAt(i)==',';
  8.       
  9.       if (isEnd) {  // ] } should always be preceded by linebreak
  10.         indent-=2;  // This line should have less indent.
  11.         System.out.println();
  12.         lastLineBreak = true;
  13.       }
  14.       if (lastLineBreak == true) { // If a new line begins, indent it.
  15.         if (s.charAt(i)==' ') continue;     // Skip spaces              
  16.         for (int j = 0; j < indent; ++j) System.out.print(" ");
  17.       }

  18.       if (isBegin) { // For [ and {, next line has more indent.
  19.         indent += 2;
  20.       }
  21.       lastLineBreak = isBegin || isComma; // Only [{, results in linebreak
  22.       System.out.print(s.charAt(i));
  23.       if (lastLineBreak) System.out.println();
  24.     }
  25.   }
复制代码
回复 支持 2 反对 0

使用道具 举报

 楼主| pinkdatura 发表于 2016-8-24 04:43:09 | 显示全部楼层
我的做法是iterative的,可是面试还是fail了,脸家店面,所以求教
  1. public static void main(String [] args) {
  2.       String s = "[1,2,3, {\"id\": 1, \"name\": \"wang\", \"tag\":[1,\"home\",2], \"price\":234}]";
  3.      String ss = "{ \"firstName\": \"John\", \"lastName\": \"Smith\", \"isAlive\": true, \"age\": 25, \"address\": { \"streetAddress\": \"21 2nd Street\", \"city\": \"New York\", \"state\": \"NY\", \"postalCode\": \"10021-3100\" }, \"phoneNumbers\": [ { \"type\": \"home\", \"number\": \"212 555-1234\" }, { \"type\": \"office\", \"number\": \"646 555-4567\" }, { \"type\": \"mobile\", \"number\": \"123 456-7890\" } ], \"children\": [], \"spouse\": nul }";


  4.      parseJson(ss);
  5.    
  6.   }
  7.   
  8.   public static String dentSpace(int dentNum) {
  9.       int count = 0;
  10.       StringBuilder sb = new StringBuilder();
  11.         while(count < dentNum){
  12.           sb.append(" ");
  13.           count++;
  14.         }
  15.       return sb.toString();

  16.   }
  17.   
  18.   public static void parseJson(String s) {
  19.       int dent = 0;
  20.       for(int i = 0; i < s.length(); i++) {
  21.            if(s.charAt(i) >= '0' && s.charAt(i) <= '9'){
  22.              StringBuilder sb = new StringBuilder();
  23.              while(i < s.length() && (s.charAt(i) >= '0' && s.charAt(i) <= '9' || s.charAt(i) == '.')){
  24.                  sb.append(s.charAt(i));
  25.                  i++;
  26.              }
  27.              String dents = dentSpace(dent);
  28.              System.out.print(dents + sb.toString());
  29.              i--;
  30.            }else if(s.charAt(i) == '[' || s.charAt(i) == '{'){
  31.                if(i != 0 && s.charAt(i-1) == ':'){
  32.                    dent++;
  33.                    System.out.print(s.charAt(i));
  34.                    continue;
  35.                }

  36.             
  37.             
  38.              String dents = dentSpace(dent);
  39.              dent++;
  40.              System.out.print("\n" + dents + s.charAt(i)+"\n");
  41.             
  42.            }else if (s.charAt(i) == ','){     

  43.                System.out.print(s.charAt(i) + "\n");
  44.            }else if(s.charAt(i) == ']' || s.charAt(i) == '}') {
  45.               dent--;
  46.               String dents = dentSpace(dent);
  47.               if(i < s.length()-1 && s.charAt(i+1) == ',' ){
  48.                  System.out.println("\n" + dents + s.charAt(i) + ",");
  49.                  i++;
  50.               }else{
  51.                  System.out.println("\n" + dents + s.charAt(i));
  52.               }
  53.               
  54.            }else if(s.charAt(i) == '\"' ){ // new string key
  55.                StringBuilder sb2 = new StringBuilder();
  56.                sb2.append(s.charAt(i));
  57.                i++;
  58.                while(i < s.length() && s.charAt(i) != '\"'){
  59.                   sb2.append(s.charAt(i));
  60.                   i++;
  61.                }
  62.                sb2.append(s.charAt(i));
  63.                String dents = dentSpace(dent);
  64.                System.out.print(dents + sb2.toString());         
  65.            }else if(s.charAt(i) == ':'){
  66.                 System.out.print(s.charAt(i));
  67.            }

  68.         
  69.       }  
复制代码
回复 支持 反对

使用道具 举报

 楼主| pinkdatura 发表于 2016-8-29 12:20:59 | 显示全部楼层
stellari 发表于 2016-8-24 15:37
代码基本意思有了,不过略微繁琐了些,而且某些地方和jsonprettyprint.com的结果有点出入。比如你的代码 ...

现在才看到,原来是leetcode大牛~感谢谢感谢~
回复 支持 反对

使用道具 举报

 楼主| pinkdatura 发表于 2016-8-29 12:34:37 | 显示全部楼层
又写了个recursion版本的,很丑,求stellari大神还有各位大牛指教~,遇到这种题真心觉得郁闷, 明明做了fb这2年多的所有店面题,可遇到新题,又fail了,求各位战友们的学习/刷题建议~
  1. public class JsonParser {

  2.     boolean isInBracket(String str, int ind){
  3.         int leftBracket = 0;
  4.         int rightBracket = 0;
  5.         int leftCurlyBracket = 0;
  6.         int rightCurlyBracket = 0;
  7.         for(int i=1;i<ind;i++){
  8.             if (str.charAt(i)=='{'){
  9.             leftCurlyBracket++;
  10.             }
  11.             if (str.charAt(i)=='}'){
  12.             rightCurlyBracket++;
  13.             }
  14.             if (str.charAt(i)=='['){
  15.             leftBracket++;
  16.             }
  17.             if (str.charAt(i)==']'){
  18.             rightBracket++;
  19.             }
  20.         }
  21.         if(str.charAt(ind)==','){
  22.             if (leftBracket>rightBracket||leftCurlyBracket>rightCurlyBracket){
  23.             return true;
  24.             }
  25.         }
  26.         return false;
  27.     }
  28.     boolean containsJsonObj(String line){
  29.     int i=0;
  30.     for(i=0;i<line.length();i++){
  31.         if(line.charAt(i)==':'){
  32.         break;
  33.         }
  34.     }
  35.     while(i<line.length()-1&&line.charAt(i+1)==' '){
  36.         i++;
  37.     }
  38.     if(i<line.length()-1){
  39.         if(line.charAt(i+1)=='['||line.charAt(i+1)=='{'){
  40.         return true;
  41.         }
  42.     }
  43.     return false;
  44.     }
  45.     char firstBracket(String line){
  46.     for(int i=0;i<line.length();i++){
  47.         if(line.charAt(i)=='['||line.charAt(i)=='{'){
  48.         return line.charAt(i);
  49.         }
  50.     }
  51.     return 'X';
  52.     }
  53.     char lastBracket(String line){
  54.         for(int i=line.length()-1;i>=0;i--){
  55.             if(line.charAt(i)==']'||line.charAt(i)=='}'){
  56.             return line.charAt(i);
  57.             }
  58.         }
  59.         return 'X';
  60.     }
  61.     public List<String> split(String line, int level){
  62.         List<Integer> splitInd = new ArrayList<Integer>();
  63.         splitInd.add(0);
  64.         for(int i=1;i<line.length()-1;i++){
  65.             if(line.charAt(i)==','){
  66.                 if(isInBracket(line,i)){
  67.                     
  68.                 }else{
  69.                     splitInd.add(i);
  70.                 }
  71.             }
  72.         }
  73.         splitInd.add(line.length()-1);
  74.         for(int i=0;i<splitInd.size()-1;i++){
  75.             String section = line.substring(splitInd.get(i)+1,splitInd.get(i+1));
  76.             for(int j=0;j<level;j++){
  77.             System.out.print("\t");
  78.             }
  79.             if (containsJsonObj(section)){
  80.             String array[]=section.split(":",2);
  81.             System.out.println(array[0]+":"+firstBracket(array[1]));
  82.             split(array[1],level+1);
  83.             }else{
  84.             System.out.println(section);
  85.             }
  86.             if (lastBracket(section)!='X'){
  87.             for(int j=0;j<level;j++){
  88.                 System.out.print("\t");
  89.             }
  90.             System.out.println(lastBracket(section));
  91.             }
  92.         }
  93.         return new ArrayList<String>();
  94.     }
  95.     public void print(String json){
  96.     List<String> lines = split(json,0);
  97.         for(int i=0;i<lines.size();i++){
  98.             System.out.println(lines.get(i));
  99.         }
  100.     }

  101.     public static void main(String args[]){
  102.     JsonParser j = new JsonParser();
  103.     String line =
  104. "{\"hello\":\"world\",\"key1\":20,\"key2\":20.3,\"foo\":{\"hello1\":\"world1\",\"hello5\":500,\"key3\":[150,200,300,\"hello\"],\"key4\":{\"hello1\":\"world1\",\"key3\":[200,300]}}}";
  105.     String ss = "{ \"firstName\": \"John\", \"lastName\": \"Smith\", \"isAlive\": true, \"age\": 25, \"address\": { \"streetAddress\": \"21 2nd Street\", \"city\": \"New York\", \"state\": \"NY\", \"postalCode\": \"10021-3100\" }, \"phoneNumbers\": [ { \"type\": \"home\", \"number\": \"212 555-1234\" }, { \"type\": \"office\", \"number\": \"646 555-4567\" }, { \"type\": \"mobile\", \"number\": \"123 456-7890\" } ], \"children\": [], \"spouse\": nul }";
  106.     j.print(ss);

  107.     }

  108. }
复制代码
回复 支持 反对

使用道具 举报

qesss 发表于 2016-9-30 01:27:22 | 显示全部楼层
这个题在interviewbit上有,我的解法,python的,在原题基础上有简化,因为原题有些corner case没什么意思。比如说我假设一定是 {a,b,c,} 这样的输入,而不是{a,b,c}。处理后者也很简单,但是会让代码结构不清晰,因此我去掉了:
  1. def prettyJSON(self, A):
  2.     r = []
  3.     t = ""
  4.     d = 0
  5.     for i in xrange(len(A)):
  6.         x = A[i]
  7.         if x in "[{":
  8.             r.append("\t"*d + x)
  9.             d += 1
  10.         elif x in "]}":
  11.             d -= 1
  12.             r.append("\t"*d + x)
  13.         elif x == ",":
  14.             r.append("\t"*d + t + ",")
  15.             t = ""
  16.         elif x == ":":
  17.             t += x
  18.             if A[i + 1] in "[{":
  19.                 r.append("\t"*d + t)
  20.                 t = ""
  21.         else:
  22.             t += x
  23.     return r
复制代码
回复 支持 反对

使用道具 举报

本版积分规则

请点这里访问我们的新网站:一亩三分地Instant.

Instant搜索更强大,不扣积分,内容组织的更好更整洁!目前仍在beta版本,努力完善中!反馈请点这里

关闭

一亩三分地推荐上一条 /5 下一条

手机版|小黑屋|一亩三分地论坛声明 ( 沪ICP备11015994号 )

custom counter

GMT+8, 2016-12-11 06:42

Powered by Discuz! X3

© 2001-2013 Comsenz Inc. Design By HUXTeam

快速回复 返回顶部 返回列表