You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ba...@apache.org on 2007/11/13 04:18:37 UTC

svn commit: r594409 - in /commons/proper/lang/trunk/src: java/org/apache/commons/lang/StringUtils.java test/org/apache/commons/lang/StringUtilsTest.java

Author: bayard
Date: Mon Nov 12 19:18:36 2007
New Revision: 594409

URL: http://svn.apache.org/viewvc?rev=594409&view=rev
Log:
Applying Scott Johnson's great work in LANG-269

Modified:
    commons/proper/lang/trunk/src/java/org/apache/commons/lang/StringUtils.java
    commons/proper/lang/trunk/src/test/org/apache/commons/lang/StringUtilsTest.java

Modified: commons/proper/lang/trunk/src/java/org/apache/commons/lang/StringUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/java/org/apache/commons/lang/StringUtils.java?rev=594409&r1=594408&r2=594409&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/java/org/apache/commons/lang/StringUtils.java (original)
+++ commons/proper/lang/trunk/src/java/org/apache/commons/lang/StringUtils.java Mon Nov 12 19:18:36 2007
@@ -69,7 +69,7 @@
  *  <li><b>Abbreviate</b>
  *      - abbreviates a string using ellipsis</li>
  *  <li><b>Difference</b>
- *      - compares two Strings and reports on their differences</li>
+ *      - compares Strings and reports on their differences</li>
  *  <li><b>LevensteinDistance</b>
  *      - the number of changes needed to change one String into another</li>
  * </ul>
@@ -116,6 +116,7 @@
  * @author Michael Davey
  * @author Reuben Sivan
  * @author Chris Hyzer
+ * @author Scott Johnson
  * @since 1.0
  * @version $Id$
  */
@@ -5007,6 +5008,148 @@
         return -1;
     }
 
+    /**
+     * <p>Compares all Strings in an array and returns the index at which the
+     * Strings begin to differ.</p>
+     *
+     * <p>For example,
+     * <code>indexOfDifference(new String[] {"i am a machine", "i am a robot"}) -> 7</code></p>
+     *
+     * <pre>
+     * StringUtils.indexOfDifference(null) = -1
+     * StringUtils.indexOfDifference(new String[] {}) = -1
+     * StringUtils.indexOfDifference(new String[] {"abc"}) = -1
+     * StringUtils.indexOfDifference(new String[] {null, null}) = -1
+     * StringUtils.indexOfDifference(new String[] {"", ""}) = -1
+     * StringUtils.indexOfDifference(new String[] {"", null}) = 0
+     * StringUtils.indexOfDifference(new String[] {"abc", null, null}) = 0
+     * StringUtils.indexOfDifference(new String[] {null, null, "abc"}) = 0
+     * StringUtils.indexOfDifference(new String[] {"", "abc"}) = 0
+     * StringUtils.indexOfDifference(new String[] {"abc", ""}) = 0
+     * StringUtils.indexOfDifference(new String[] {"abc", "abc"}) = -1
+     * StringUtils.indexOfDifference(new String[] {"abc", "a"}) = 1
+     * StringUtils.indexOfDifference(new String[] {"ab", "abxyz"}) = 2
+     * StringUtils.indexOfDifference(new String[] {"abcde", "abxyz"}) = 2
+     * StringUtils.indexOfDifference(new String[] {"abcde", "xyz"}) = 0
+     * StringUtils.indexOfDifference(new String[] {"xyz", "abcde"}) = 0
+     * StringUtils.indexOfDifference(new String[] {"i am a machine", "i am a robot"}) = 7
+     * </pre>
+     *
+     * @param strs  array of strings, entries may be null
+     * @return the index where the strings begin to differ; -1 if they are all equal
+     */
+    public static int indexOfDifference(String[] strs) {
+        if (strs == null || strs.length <= 1) {
+            return -1;
+        }
+        boolean anyStringNull = false;
+        boolean allStringsNull = true;
+        int arrayLen = strs.length;
+        int shortestStrLen = Integer.MAX_VALUE;
+        int longestStrLen = 0;
+
+        // find the min and max string lengths; this avoids checking to make 
+        // sure we are not exceeding the length of the string each time through
+        // the bottom loop.
+        for (int i=0; i<arrayLen; i++) {
+            if (strs[i] == null) {
+                anyStringNull = true;
+                shortestStrLen = 0;
+            } else {   
+                allStringsNull = false;
+                shortestStrLen = Math.min(strs[i].length(), shortestStrLen);
+                longestStrLen = Math.max(strs[i].length(), longestStrLen);
+            }
+        }
+
+        // handle lists containing all nulls or all empty strings
+        if (allStringsNull || (longestStrLen == 0 && !anyStringNull)) {
+            return -1;
+        }
+
+        // handle lists containing some nulls or some empty strings
+        if (shortestStrLen == 0) {
+            return 0;
+        } 
+
+        // find the position with the first difference across all strings
+        int firstDiff = -1;
+        for (int stringPos = 0; stringPos<shortestStrLen; stringPos++) {
+            char comparisonChar = strs[0].charAt(stringPos);
+            for (int arrayPos = 1; arrayPos<arrayLen; arrayPos++) {
+                if (strs[arrayPos].charAt(stringPos) != comparisonChar) {
+                    firstDiff = stringPos;
+                    break;
+                }
+            }
+            if (firstDiff != -1) {
+                break;
+            }
+        }
+
+        if (firstDiff == -1 && shortestStrLen != longestStrLen) {
+            // we compared all of the characters up to the length of the 
+            // shortest string and didn't find a match, but the string lengths 
+            // vary, so return the length of the shortest string.
+            return shortestStrLen;
+        } else {
+            return firstDiff;
+        }
+    }
+    
+    /**
+     * <p>Compares all Strings in an array and returns the initial sequence of 
+     * characters that is common to all of them.</p>
+     *
+     * <p>For example,
+     * <code>getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) -> "i am a "</code></p>
+     *
+     * <pre>
+     * StringUtils.getCommonPrefix(null) = ""
+     * StringUtils.getCommonPrefix(new String[] {}) = ""
+     * StringUtils.getCommonPrefix(new String[] {"abc"}) = "abc"
+     * StringUtils.getCommonPrefix(new String[] {null, null}) = ""
+     * StringUtils.getCommonPrefix(new String[] {"", ""}) = ""
+     * StringUtils.getCommonPrefix(new String[] {"", null}) = ""
+     * StringUtils.getCommonPrefix(new String[] {"abc", null, null}) = ""
+     * StringUtils.getCommonPrefix(new String[] {null, null, "abc"}) = ""
+     * StringUtils.getCommonPrefix(new String[] {"", "abc"}) = ""
+     * StringUtils.getCommonPrefix(new String[] {"abc", ""}) = ""
+     * StringUtils.getCommonPrefix(new String[] {"abc", "abc"}) = "abc"
+     * StringUtils.getCommonPrefix(new String[] {"abc", "a"}) = "a"
+     * StringUtils.getCommonPrefix(new String[] {"ab", "abxyz"}) = "ab"
+     * StringUtils.getCommonPrefix(new String[] {"abcde", "abxyz"}) = "ab"
+     * StringUtils.getCommonPrefix(new String[] {"abcde", "xyz"}) = ""
+     * StringUtils.getCommonPrefix(new String[] {"xyz", "abcde"}) = ""
+     * StringUtils.getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) = "i am a "
+     * </pre>
+     *
+     * @param strs  array of String objects, entries may be null
+     * @return the initial sequence of characters that are common to all Strings
+     * in the array; empty String if the array is null or the strings in the
+     * array are all null; -1 if all Strings are equal
+     */
+    public static String getCommonPrefix(String[] strs) {
+        if (strs == null || strs.length == 0) {
+            return EMPTY;
+        }
+        int smallestIndexOfDiff = indexOfDifference(strs);
+        if (smallestIndexOfDiff == -1) {
+            // all strings were identical
+            if (strs[0] == null) {
+                return EMPTY;
+            } else {
+                return strs[0];
+            }
+        } else if (smallestIndexOfDiff == 0) {
+            // there were no common initial characters
+            return EMPTY;
+        } else {
+            // we found a common initial character sequence 
+            return strs[0].substring(0, smallestIndexOfDiff);
+        }
+    }  
+    
     // Misc
     //-----------------------------------------------------------------------
     /**

Modified: commons/proper/lang/trunk/src/test/org/apache/commons/lang/StringUtilsTest.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/org/apache/commons/lang/StringUtilsTest.java?rev=594409&r1=594408&r2=594409&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/test/org/apache/commons/lang/StringUtilsTest.java (original)
+++ commons/proper/lang/trunk/src/test/org/apache/commons/lang/StringUtilsTest.java Mon Nov 12 19:18:36 2007
@@ -39,6 +39,7 @@
  * @author <a href="hps@intermeta.de">Henning P. Schmiedehausen</a>
  * @author Phil Steitz
  * @author Gary D. Gregory
+ * @author Scott Johnson
  * @author Al Chou
  * @version $Id$
  */
@@ -1619,4 +1620,45 @@
         assertEquals("queued", StringUtils.remove("queued", 'z'));
     }
 
+    
+    public void testDifferenceAt_StringArray(){        
+        assertEquals(-1, StringUtils.indexOfDifference(null));
+        assertEquals(-1, StringUtils.indexOfDifference(new String[] {}));
+        assertEquals(-1, StringUtils.indexOfDifference(new String[] {"abc"}));
+        assertEquals(-1, StringUtils.indexOfDifference(new String[] {null, null}));
+        assertEquals(-1, StringUtils.indexOfDifference(new String[] {"", ""}));
+        assertEquals(0, StringUtils.indexOfDifference(new String[] {"", null}));
+        assertEquals(0, StringUtils.indexOfDifference(new String[] {"abc", null, null}));
+        assertEquals(0, StringUtils.indexOfDifference(new String[] {null, null, "abc"}));
+        assertEquals(0, StringUtils.indexOfDifference(new String[] {"", "abc"}));
+        assertEquals(0, StringUtils.indexOfDifference(new String[] {"abc", ""}));
+        assertEquals(-1, StringUtils.indexOfDifference(new String[] {"abc", "abc"}));
+        assertEquals(1, StringUtils.indexOfDifference(new String[] {"abc", "a"}));
+        assertEquals(2, StringUtils.indexOfDifference(new String[] {"ab", "abxyz"}));
+        assertEquals(2, StringUtils.indexOfDifference(new String[] {"abcde", "abxyz"}));
+        assertEquals(0, StringUtils.indexOfDifference(new String[] {"abcde", "xyz"}));
+        assertEquals(0, StringUtils.indexOfDifference(new String[] {"xyz", "abcde"}));
+        assertEquals(7, StringUtils.indexOfDifference(new String[] {"i am a machine", "i am a robot"}));
+    }
+    
+    public void testGetCommonPrefix_StringArray(){        
+        assertEquals("", StringUtils.getCommonPrefix(null));
+        assertEquals("", StringUtils.getCommonPrefix(new String[] {}));
+        assertEquals("abc", StringUtils.getCommonPrefix(new String[] {"abc"}));
+        assertEquals("", StringUtils.getCommonPrefix(new String[] {null, null}));
+        assertEquals("", StringUtils.getCommonPrefix(new String[] {"", ""}));
+        assertEquals("", StringUtils.getCommonPrefix(new String[] {"", null}));
+        assertEquals("", StringUtils.getCommonPrefix(new String[] {"abc", null, null}));
+        assertEquals("", StringUtils.getCommonPrefix(new String[] {null, null, "abc"}));
+        assertEquals("", StringUtils.getCommonPrefix(new String[] {"", "abc"}));
+        assertEquals("", StringUtils.getCommonPrefix(new String[] {"abc", ""}));
+        assertEquals("abc", StringUtils.getCommonPrefix(new String[] {"abc", "abc"}));
+        assertEquals("a", StringUtils.getCommonPrefix(new String[] {"abc", "a"}));
+        assertEquals("ab", StringUtils.getCommonPrefix(new String[] {"ab", "abxyz"}));
+        assertEquals("ab", StringUtils.getCommonPrefix(new String[] {"abcde", "abxyz"}));
+        assertEquals("", StringUtils.getCommonPrefix(new String[] {"abcde", "xyz"}));
+        assertEquals("", StringUtils.getCommonPrefix(new String[] {"xyz", "abcde"}));
+        assertEquals("i am a ", StringUtils.getCommonPrefix(new String[] {"i am a machine", "i am a robot"}));
+    }
+ 
 }