通过排序自然秩序的字符串数组,而忽略空格 [英] Sorting a string array by Natural Order and ignore spaces

查看:209
本文介绍了通过排序自然秩序的字符串数组,而忽略空格的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现这个样本code在这个论坛发表<一个href=\"http://stackoverflow.com/questions/1262239/natural-sort-order-string-comparison-in-java-is-one-built-in/1262345#comment16877348_1262345\">Yishai,它的作品真的很好。
它可以帮助我排序文件在磁盘上找到的名称在自然秩序,即人类的方式喜欢看这样的:


  • 文件1

    文件2

    文件3

    FILE11


如果这只是正常的(ASCII),然后排序在 FILE11 会来后,在文件1 之前的文件2

问题是如何改善这一code,使一个选项,空格可以忽略不计,它可以在一个长长的清单就像读文件名排序时非常有用的类型:


  • 文件1

    文件1

    文件2

    文件3


下面是code

  Col​​lections.sort(myStringArrayList,
                 新AlphanumComparator(String.CASE_INSENSITIVE_ORDER)); / *
 *本Alphanum算法是串改进的排序算法
 *包含数字。相反,在ASCII顺序排序号的像
 *标准的排序,这个算法排序按数字顺序编号。
 *
 *本Alphanum算法在http://www.DaveKoelle.com讨论
 *
 *
 *这个库是免费软件;您可以重新分配和/或
 *修改它的GNU宽通用公共条款
 *公布由自由软件基金会许可证;或
 *许可,或更新版本的2.1版。
 *
 *此库分布在希望这将是有益的,
 *但没有任何担保;甚至没有的隐含担保
 *适销性或适用于特定用途。请参阅GNU
 *详细宽通用公共许可证。
 *
 *您应该已经收到GNU宽通用公共副本
 *函数库一起许可证;如果没有,请写信给自由软件
 *基金公司,51街富兰克林五楼,波士顿,MA 0​​2110-1301 USA
 *
 * /进口了java.util.Comparator;/ **
 *这是一个更新的版本与丹尼尔Migowski的增强,
 *安德烈虚假,大卫Koelle
 *
 *转而使用模板(Java的1.5+):
 * - 改变执行比较到实现比较&LT;串GT;
 * - 更改比较(对象01,对象02)到比较(字符串S1,S2的字符串)
 * - 在取下类型检查和铸造比较()。
 *
 *要使用这个类:
 *使用从java.util.Collections中的类静态的排序的方法:
 * Collections.sort(您的清单,新AlphanumComparator());
 * /
公共类AlphanumComparator实现比较&LT;串GT;
{
    私人比较&LT;串GT;比较=新NaturalComparator();    公共AlphanumComparator(比较&LT;串GT;比较){
        this.comparator =比较;
    }    公共AlphanumComparator(){    }    私人最终布尔ISDIGIT(CHAR CH)
    {
        返回CH&GT; = 48安培;&安培; CH&LT; = 57;
    }    / **字符串的长度对于提高工作效率传递(只需要一次来计算的话)** /
    私人最终字符串的GetChunk(一个String,诠释slength,INT标志)
    {
        StringBuilder的块=新的StringBuilder();
        焦C = s.charAt(标记);
        chunk.append(C);
        标志++;
        如果(ISDIGIT(c))的
        {
            而(标记&LT; slength)
            {
                C = s.charAt(标记);
                如果(!ISDIGIT(c))的
                    打破;
                chunk.append(C);
                标志++;
            }
        }其他
        {
            而(标记&LT; slength)
            {
                C = s.charAt(标记);
                如果(ISDIGIT(c))的
                    打破;
                chunk.append(C);
                标志++;
            }
        }
        返回chunk.toString();
    }    公众诠释比较(字符串S1,S2的字符串)
    {        INT thisMarker = 0;
        INT thatMarker = 0;
        INT s1Length = s1.length();
        INT s2Length = s2.length();        而(thisMarker&LT; s1Length&放大器;&安培; thatMarker&LT; s2Length)
        {
            串thisChunk =的GetChunk(S1,s1Length,thisMarker);
            thisMarker + = thisChunk.length();            串thatChunk =的GetChunk(S2,s2Length,thatMarker);
            thatMarker + = thatChunk.length();            //如果两个块包含数字字符,数字进行排序
            INT结果为0;
            如果(ISDIGIT(thisChunk.charAt(0))及&放大器; ISDIGIT(thatChunk.charAt(0)))
            {
                //通过简单的长块比较。
                INT thisChunkLength = thisChunk.length();
                结果= thisChunkLength - thatChunk.length();
                //如果相等,所述第一不同数目计数
                如果(结果== 0)
                {
                    的for(int i = 0; I&LT; thisChunkLength;我++)
                    {
                        结果= thisChunk.charAt(ⅰ) - thatChunk.charAt(ⅰ);
                        如果(结果!= 0)
                        {
                            返回结果;
                        }
                    }
                }
            }其他
            {
                结果=执行comparator.compare(thisChunk,thatChunk);
            }            如果(结果!= 0)
                返回结果;
        }        返回s1Length - s2Length;
    }    私有静态类NaturalComparator实现比较&LT;串GT; {
        公众诠释比较(字符串O1,O2的字符串){
            返回o1.compareTo(02);
        }
    }


解决方案

一个简单的解决方案,它应该通过四种情况下,你presented是通过同一codeA定制的比较,看起来的构造函数的测试像这样的:

 公共类SpaceInsensitiveComparator实现比较&LT;串GT; {
    公众诠释比较(字符串O1,O2的字符串){
        返回o1.trim()的compareTo(o2.trim())。
    }
 }

或为不区分大小写:

 公共类SpaceInsensitiveComparator实现比较&LT;串GT; {
    公众诠释比较(字符串O1,O2的字符串){
        返回String.CASE_INSENSITIVE_ORDER.compare(o1.trim(),o2.trim());
    }
 }

I've found this sample code posted on this forum by Yishai, which works really well. It helps me sort file names found on the disk in a "natural order", i.e. the way humans like to see like:

  • file1

    file2

    file3

    file11

If it was just the normal (ascii) sorting then the file11 would come after the file1 and before file2

The question is how to improve on this code and make an option that spaces can be ignored, which can be very useful type of sorting when reading file names in a long list like:

  • file1

    file 1

    file2

    file 3

Here is the code

Collections.sort(myStringArrayList, 
                 new AlphanumComparator(String.CASE_INSENSITIVE_ORDER));



 /*
 * The Alphanum Algorithm is an improved sorting algorithm for strings 
 * containing numbers.  Instead of sorting numbers in ASCII order like 
 * a standard sort, this algorithm sorts numbers in numeric order. 
 * 
 * The Alphanum Algorithm is discussed at http://www.DaveKoelle.com 
 * 
 * 
 * This library is free software; you can redistribute it and/or 
 * modify it under the terms of the GNU Lesser General Public 
 * License as published by the Free Software Foundation; either 
 * version 2.1 of the License, or any later version. 
 * 
 * This library is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
 * Lesser General Public License for more details. 
 * 
 * You should have received a copy of the GNU Lesser General Public 
 * License along with this library; if not, write to the Free Software 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA 
 * 
 */ 

import java.util.Comparator; 

/** 
 * This is an updated version with enhancements made by Daniel Migowski, 
 * Andre Bogus, and David Koelle 
 * 
 * To convert to use Templates (Java 1.5+): 
 *   - Change "implements Comparator" to "implements Comparator<String>" 
 *   - Change "compare(Object o1, Object o2)" to "compare(String s1, String s2)" 
 *   - Remove the type checking and casting in compare(). 
 * 
 * To use this class: 
 *   Use the static "sort" method from the java.util.Collections class: 
 *   Collections.sort(your list, new AlphanumComparator()); 
 */ 
public class AlphanumComparator implements Comparator<String> 
{ 
    private Comparator<String> comparator = new NaturalComparator(); 

    public AlphanumComparator(Comparator<String> comparator) { 
        this.comparator = comparator; 
    } 

    public AlphanumComparator() { 

    } 

    private final boolean isDigit(char ch) 
    { 
        return ch >= 48 && ch <= 57; 
    } 

    /** Length of string is passed in for improved efficiency (only need to calculate it once) **/ 
    private final String getChunk(String s, int slength, int marker) 
    { 
        StringBuilder chunk = new StringBuilder(); 
        char c = s.charAt(marker); 
        chunk.append(c); 
        marker++; 
        if (isDigit(c)) 
        { 
            while (marker < slength) 
            { 
                c = s.charAt(marker); 
                if (!isDigit(c)) 
                    break; 
                chunk.append(c); 
                marker++; 
            } 
        } else 
        { 
            while (marker < slength) 
            { 
                c = s.charAt(marker); 
                if (isDigit(c)) 
                    break; 
                chunk.append(c); 
                marker++; 
            } 
        } 
        return chunk.toString(); 
    } 

    public int compare(String s1, String s2) 
    { 

        int thisMarker = 0; 
        int thatMarker = 0; 
        int s1Length = s1.length(); 
        int s2Length = s2.length(); 

        while (thisMarker < s1Length && thatMarker < s2Length) 
        { 
            String thisChunk = getChunk(s1, s1Length, thisMarker); 
            thisMarker += thisChunk.length(); 

            String thatChunk = getChunk(s2, s2Length, thatMarker); 
            thatMarker += thatChunk.length(); 

            // If both chunks contain numeric characters, sort them numerically 
            int result = 0; 
            if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0))) 
            { 
                // Simple chunk comparison by length. 
                int thisChunkLength = thisChunk.length(); 
                result = thisChunkLength - thatChunk.length(); 
                // If equal, the first different number counts 
                if (result == 0) 
                { 
                    for (int i = 0; i < thisChunkLength; i++) 
                    { 
                        result = thisChunk.charAt(i) - thatChunk.charAt(i); 
                        if (result != 0) 
                        { 
                            return result; 
                        } 
                    } 
                } 
            } else 
            { 
                result = comparator.compare(thisChunk, thatChunk); 
            } 

            if (result != 0) 
                return result; 
        } 

        return s1Length - s2Length; 
    } 

    private static class NaturalComparator implements Comparator<String> { 
        public int compare(String o1, String o2) { 
            return o1.compareTo(o2); 
        } 
    } 

解决方案

A simple solution which should pass the test of the four cases you presented is to pass the constructor of that same code a custom comparator that looks like this:

 public class SpaceInsensitiveComparator implements Comparator<String> {   
    public int compare(String o1, String o2) {   
        return o1.trim().compareTo(o2.trim());   
    }   
 } 

Or for case insensitivity:

 public class SpaceInsensitiveComparator implements Comparator<String> {   
    public int compare(String o1, String o2) {   
        return String.CASE_INSENSITIVE_ORDER.compare(o1.trim(), o2.trim());   
    }   
 } 

这篇关于通过排序自然秩序的字符串数组,而忽略空格的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆