سؤال

Java الخاص بي صدئ للغاية وأنا عالق في محاولة لإنشاء واجهة مستخدم تبسط تنفيذ البرامج النصية Shell أو ملفات الدُفعات اعتمادًا على ما إذا كانت Linus أو Win32 على التوالي. الملفات لديها اتفاقية التسمية التالية.

  module-verb-object-etc [args-list]
  mysql-connect-grid
  mysql-connect-rds
  mysql-dump-grid
  mysql-dump-grid-se314

في النهاية ، أود أن يحلل مصطلحات لا لبس فيها حتى أتمكن من ذلك:

  1. رمز الأوامر (على سبيل المثال المحدد بواسطة "-") وقصرها في مصطلحات مبسطة ، مثل نافذة أوامر Foxpro أو iOS الخاص بـ Cisco (على سبيل المثال "My CO GR" ينفذ "MySql-Connect-Grid" في UNIX و *.CMD في Win32)
  2. وأيضًا في نمط iOS ، السماح للمستخدم بإدخال أوامر مختصرة حتى يتمكنوا من كتابة علامة استفهام (؟) وسيمنحهم تلميحًا فيما يتعلق بخيارات الأوامر الفريدة (أو التالية) المتبقية (على سبيل المثال "My؟" إرجاع mysql و "my؟" إرجاع الاتصال ، أو تفريغ). ستكون قيم إرجاع OTHR "غامضة" أو "غير معروفة" للأوامر غير الفريدة أو لا يمكن مطابقتها. قد يبدو هذا تافهًا ولكن هناك مئات الأوامر في كل مجلد ولا يريدون المستخدمون التفكير ...

لقد كتبت وظيفة لسحب قائمة الملفات من دليل وإعادة مجموعة من FileAnmes. ثم أقوم بتحويل ذلك إلى صفيف ثنائي الأبعاد باستخدام الطريقة أدناه التي تُرجع شبكة بحجم ديناميكي من الأوامر المحتملة.

    /**********************************************************************************
     *  MAKE GRID: Parses array of filenames and tokenizes AWS cmds.
     * @param strs  Array of filenames
     **********************************************************************************/
     public static String [][] makeGrid(String strs[], boolean bPrint) {
       String tmpGrid[][];
       int nMaxCols = 0;
       int nRows = uniqueCount(strs);
       int nGridRow = 0; 
       tmpGrid = new String [nRows][]; 
       for (int nRow=0; nRow<nRows; nRow++) { 
 String cFilename = strs[nRow];
                if (!cFilename.endsWith(".cmd") // just list unix files (filter for batch files)
    && cFilename.indexOf("-") > 0 ) // make sure there's a dash in the filename
    {
           String strTokens[] = tokenize(strs[nRow], "-"); // the dash is our token deliminator
           int nCols = strTokens.length; 
           if (nCols>nMaxCols) nMaxCols=nCols;
           tmpGrid[nGridRow] = new String [nCols];
           for (int nCol=0; nCol<nCols; nCol++) { 
               tmpGrid[nGridRow][nCol] = strTokens[nCol];
               if (bPrint) System.out.print(" "+tmpGrid[nGridRow][nCol]);
             }
            nGridRow++;
            if (bPrint) System.out.println("");
     } //end-if
         }
       String[][] cmdGrid = new String[nGridRow][nMaxCols];
       System.arraycopy(tmpGrid, 0, cmdGrid, 0, nGridRow); // removes null rows  (&NPEs!)
       return cmdGrid;
      }

هذا يعيد صفيف ثنائي الأبعاد (أدناه) ، لذلك grid[Row-N][Col-0] هي مباراة. أرغب في سحب القيم المتميزة فقط حيث row[0] هي مباراة Wildcard لـ cmdToken[0] && row[1] يشبه" cmdToken[1] بحيث يمكن للمستخدمين تجميع الأمر حتى "my du gr ?" عائدات "ENTER, [se314]" - إذا كان ذلك منطقيًا ...

String[][] makeGrid:
    mysql dump grid se314
    mysql connect grid
    mysql dump grid
    mysql connect rds

التحدي الخاص بي: لا يمكنني الحصول على رأسي حول وظيفة المطابقة في جافا. إذا كان SQL سيكون شيئًا مثل:

"SELECT DISTINCT col2 FROM cmd_Grid
   WHERE col1 LIKE 'cmdToken1%' " 

أو حتى أفضل: تعيين عمق INT بشكل متكرر لكل عمود متتالي

`SELECT DISTINCT col+str(depthmark+1) FROM cmd_Grid 
    WHERE col+str(depthmark) LIKE 'cmdMatchedTokens%' " 

حتى يكون لديك تطابق دقيق.

لقد وجدت حزمة تسمى JOSQL التي جربتها من اليأس ، لكن يبدو أنني لا أستطيع أن أجعلها تعمل في Java6. على أي حال: كنت آمل أيضًا في حل جافا نقيًا بحيث يمكن احتواء كل شيء في فصل واحد ...

ربما باستخدام الماسح الضوئي أو أي شيء لتحليل صفيف بلدي متعدد التقدم للقيم الفريدة ... أعرف أنني ربما أجعلها أكثر تعقيدًا مما يجب أن يكون.

سيكون موضع تقدير لطيف في الاتجاه الصحيح.

تيا

هل كانت مفيدة؟

المحلول

يمكن أن يكون أحد الحلول الشاملة هو تخفيض هاشماب ، بحيث يكون المفتاح أمرًا قصيرًا محتملًا مثل "CO GR" والقيمة المقابلة هي "شبكة MySQL-Connect-Grid". لذلك ستكون هناك قيم في خريطة التجزئة التي سيكون لها " MySQL-Connect-Grid "كقيمة.

ولكن هذا حل ممكن فقط إذا كان هناك عدد محدود من المفاتيح الممكنة. إذا لم يكن هذا هو الحال ، فيمكنك استخدام طرق تحليل السلسلة المدمجة.

علي سبيل المثال:

    String[][] makeGrid = new String[][]{{"mysql", "dump", "grid", "se314"}, 
              {"mysql", "connect", "grid", ""},
              {"mysql",  "dump", "grid", ""},
              {"mysql", "connect", "rds", ""}
              };
     String[] query2 = new String[]{"my", "du", "gr"};

  String[][] matchingCommands = new String[4][4];
  int resultSize = 0;
     for(int i=0; i<makeGrid.length; i++)
  {
      String[] commandColumn = makeGrid[i];
   boolean matches = false;
      for(int cnt=0; cnt<commandColumn.length; cnt++)
      {
       String commandPart = commandColumn[cnt];
       if(cnt < query2.length){
        String queryPart = query2[cnt];
     if(commandPart.startsWith(queryPart) || queryPart.equals("?")){
         matches = true;
        }else{
         matches = false;
         break;
        }
       }
      }
      if(matches){
       matchingCommands[resultSize] = commandColumn;
       resultSize++;
      }
  }

يجب أن يعطيك مقتطف الرمز هذا فكرة عن كيفية القيام بذلك. هناك شيء واحد يجب ملاحظته هنا. ال MatchingCommands تمت تهيئة Array إلى الصفوف الأربعة و 4 أعمدة مضيئة لأن المباريات ستكون أقل من ذلك. اسمحوا لي أن أعرف إذا كنت بحاجة إلى مساعدة في جعل هذا أكثر كفاءة. وإلا ، فهذا جزء من التعليمات البرمجية التي أعتقد أنها تفعل ما تريد.

نصائح أخرى

يمكنك أيضًا البحث في استخدام بعض هياكل البيانات الأكثر تقدمًا مثل قائمة ArrayList بدلاً من صفيف واستخدام StringTokenizer لإنشاء كل جزء أمر أثناء الطيران.

سيكون شيئًا كهذا:

ArrayList<String> matchingCommands = new ArrayList<String>();

    ArrayList<String> commandList = new ArrayList<String>();
    commandList.add("mysql dump grid se314");
    commandList.add("mysql connect grid");
    commandList.add("mysql dump grid");
    commandList.add("mysql connect rds");

    String queryCommand = "my du gr ?";

    for(int i=0; i<commandList.size(); i++)
    {
        boolean matches = false;
        String command = commandList.get(i);
        StringTokenizer commandTokenizer = new StringTokenizer(command, " "); // Using space as the deliminator
        StringTokenizer queryTokenizer = new StringTokenizer(queryCommand, " "); // Using space as the deliminator

        while(commandTokenizer.hasMoreTokens())
        {
            String queryPart = queryTokenizer.nextToken();
            String commandPart = commandTokenizer.nextToken();
            if(commandPart.startsWith(queryPart) || queryPart.equals("?")){
                matches = true;
            }else{
                matches = false;
                break;
            }
        }
        if(matches){
            matchingCommands.add(command);
        }
    }
    System.out.println(matchingCommands);

هذا من شأنه أن يتأكد من أن برنامجك يمكن أن ينمو ديناميكيًا ولا يوجد هدر للذاكرة بسبب الكائنات الفارغة أيضًا.

في الوقت الحالي ، كنت أتجول مع تحليل كل cmdstring (الاستعلام) لمحددات الفضاء الأبيض ورمز المصفوفة. شيء مثل:

 Scanner sCmdString = new Scanner(cInput);
 while (sCmdString.hasNext()) { 
 String cToken = sCmdString.next().toUpperCase().trim();
 System.out.println(" "+cToken+" ");
 // match cmdString[i..n] to cmdGrid
 for (int nRow=0; nRow < cmdGrid.length; nRow++) {
       for (int nCol=0; nCol < cmdGrid[nRow].length; nCol++) {
  if (cmdGrid[nRow][nCol].equalsIgnoreCase(cToken) )
     System.out.println("MATCH: "+cmdGrid[nRow][nCol]);
  else System.out.println("NO MATCH:"+cmdGrid[nRow][nCol].toUpperCase()+":"+cToken+"...");
        }
   }
   }

لكنني كنت أحصل على NPEs مع أطوال الصف غير المتكافئة.

وأنا أحب فكرتك عن تسطيح الأعمدة.

أعتقد أنه لا يزال يتعين علي إزالة التكرارات ... لا؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top