对月份(带字符串)排序算法

发布于 2024-08-18 06:37:28 字数 301 浏览 2 评论 0原文

我有这个月的数组:

["January", "March", "December" , "October" ]

我想将其排序如下:

["January", "March", "October", "December" ] 

我目前正在思考“if/else”可怕的级联,但我想知道是否还有其他方法可以做到这一点。

不好的部分是我只需要使用“字符串”来执行此操作(即不使用 Date 对象或类似的东西)

什么是一个好的方法?

I have this months array:

["January", "March", "December" , "October" ]

And I want to have it sorted like this:

["January", "March", "October", "December" ] 

I'm currently thinking in a "if/else" horrible cascade but I wonder if there is some other way to do this.

The bad part is that I need to do this only with "string" ( that is, without using Date object or anything like that )

What would be a good approach?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

£冰雨忧蓝° 2024-08-25 06:37:28

如果我有办法提供自定义排序顺序,我会创建一个定义正确顺序的列表:

correct = List("January", "February", "March", ...)

然后按该列表中的位置排序,如下所示:

toSort.sort(a, b) => compare(correct.index(a), correct.index(b))

If I had a way to supply a custom sorting order, I'd create a list defining the correct order:

correct = List("January", "February", "March", ...)

And then sort by the position in that list, something like:

toSort.sort(a, b) => compare(correct.index(a), correct.index(b))
梦里°也失望 2024-08-25 06:37:28

创建一个包含 name->index 的表,然后根据数组在表中的值对数组进行排序。

几个示例可能有用,在 C# 中 arr.sort(myCompare) 中,在 Java 中 Collections.sort(arr, myCompare) 中,在 Python 中 arr.sort (myCompare),在 PHP 中 usort($arr, 'myCompare'),在 C++ 中 sort(vec.begin(), vec.end(), myCompare)代码>.

Create a table with name->index, then sort the array based on its value in the table.

A couple of examples may be useful, in C# arr.sort(myCompare), in Java Collections.sort(arr, myCompare), in Python arr.sort(myCompare), in PHP usort($arr, 'myCompare'), in C++ sort(vec.begin(), vec.end(), myCompare).

源来凯始玺欢你 2024-08-25 06:37:28

拥有一个具有正确排序的数组,并基于它进行排序。

另一个解决方案(如果您的语言支持)是拥有一个从月份名称到数字 (1..12) 的关联数组,并使用自定义比较器在数组上运行排序。

Perl 中的解决方案:D

my @mon = qw( January February March April May June July August September October November December );
my $mon;
@{$mon}{@mon} = (0..$#mon);

sub by_month {
    $mon->{$a} <=> $mon->{$b};
}

sort by_month @data_to_sort

(尽管我确信高尔夫球手可以在 < 30 个字符内做到这一点)

,这是纯 C 中的解决方案: http://www.pnambic.com/CPS/SortAnal/html/MonOrder.html

Have an array with the proper sort, and sort based on it.

Another solution (if your language supports it) is to have an associative array from month names to numbers (1..12) and use a custom comparator running sort on your array.

Solution in Perl :D

my @mon = qw( January February March April May June July August September October November December );
my $mon;
@{$mon}{@mon} = (0..$#mon);

sub by_month {
    $mon->{$a} <=> $mon->{$b};
}

sort by_month @data_to_sort

(although I'm sure a golfer could do that in < 30 characters)

And here's a solution in plain C : http://www.pnambic.com/CPS/SortAnal/html/MonOrder.html

依 靠 2024-08-25 06:37:28

从 Java POV 的角度来说,我要拉皮条(就像我经常做的那样)google-collections (很快将被 Guava 取代):

Arrays.sort(myMonths, Ordering.explicit("Jan", "Feb", "Mar", ....));

...以及你完成了。

如果其他人已经这样做了,那么就不要自己编写它,这可能比您可能更有效并且使用更好的 API。

在一般情况下没有帮助,但以防万一任何 Java 人员遇到同样的问题......

Talking from a Java POV, I'm going to pimp (as I often do) google-collections (soon to be replaced with Guava):

Arrays.sort(myMonths, Ordering.explicit("Jan", "Feb", "Mar", ....));

... and you're done.

Don't write it yourself if someone else has done it, probably more efficiently and with a nicer API than you probably would.

Not helpful in the general case, but just in case any Java folk have the same problem...

〆凄凉。 2024-08-25 06:37:28

同事们,

我看到这个问题/业务问题持续了两年多。
我决定编写比较器来正确排序月份的名称(存储为字符串)。
它还包含所需区域设置的月份名称
============== 比较器 =========================

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;

import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/**
 *
 * @author akashtalyan
 */
public class MonthNamesComparator implements Comparator {

    private static Map<Locale, List> monthMap = new HashMap<Locale, List>();
    private final Locale locale;

    public MonthNamesComparator(Locale locale) {
        if (locale == null) {

            throw new NullPointerException("MonthNamesComparator cannot accept null value for Locale parameter.");
        }
        List months = new ArrayList(12);
        Calendar cal = Calendar.getInstance(locale);
        SimpleDateFormat dateFormat = new SimpleDateFormat("MMMM", locale);
        this.locale = locale;
        if (!monthMap.containsKey(locale)) {
            for (int i = 0; i < 12; i++) {
                cal.set(Calendar.MONTH, i);
                months.add(dateFormat.format(cal.getTime()).toLowerCase());
            }
            monthMap.put(locale , months);
        }
    }

    @Override
    public int compare(Object month1, Object month2) {
        List months = monthMap.get(this.locale);
        if (months == null) {
            throw new NullPointerException("MonthNamesComparator cannot perform comparison - internal data is not initialized properly.");
        }
        return (months.indexOf(((String) month1).toLowerCase()) - months.indexOf(((String) month2).toLowerCase()));

    }
}

POC 的简单测试类:

import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

/**
 *
 * @author akashtalyan
 */
public class TestMonths {
    public static void main(String[] args){
        Locale en = Locale.ENGLISH, ru = new Locale("ru","RU");
        String[] monthsToTestEn = new String[] {"FebRUary", "maY", "sepTember", "january", "december"};
        String[] monthsToTestRu = new String[] {"АпреЛь", "январь", "Март", "Август"};

        Map map = new TreeMap(new MonthNamesComparator(en));
        int i = 0;
        System.out.println("En Map original:");
        for (String month : monthsToTestEn) {
            System.out.print(month + " ");
            map.put(month, new StringBuilder(String.valueOf(++i)).append(" position in source array").toString());
        }
            System.out.println();
            System.out.println("En Map sorted:");
        for (String month : (Set<String>)map.keySet()) {
            System.out.println(month + " " + map.get(month));
        }
        i = 0;
        map = new TreeMap(new MonthNamesComparator(ru));
        System.out.println("Ru Map original:");
        for (String month : monthsToTestRu) {
            System.out.print(month + " ");
            map.put(month, new StringBuilder(String.valueOf(++i)).append(" position in source array").toString());
        }
            System.out.println();
        System.out.println("Ru Map sorted:");
        for (String month : (Set<String>)map.keySet()) {
            System.out.println(month + " " + map.get(month));
        }
    }

}

享受它,就像一种魅力。

Colleagues,

I see the issue/business problem lasts more than 2 year.
I decided to write comparator for sorting months' names (stored as strings) properly.
It also holds names of the months for desired locale
============== Comparator =======================

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;

import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/**
 *
 * @author akashtalyan
 */
public class MonthNamesComparator implements Comparator {

    private static Map<Locale, List> monthMap = new HashMap<Locale, List>();
    private final Locale locale;

    public MonthNamesComparator(Locale locale) {
        if (locale == null) {

            throw new NullPointerException("MonthNamesComparator cannot accept null value for Locale parameter.");
        }
        List months = new ArrayList(12);
        Calendar cal = Calendar.getInstance(locale);
        SimpleDateFormat dateFormat = new SimpleDateFormat("MMMM", locale);
        this.locale = locale;
        if (!monthMap.containsKey(locale)) {
            for (int i = 0; i < 12; i++) {
                cal.set(Calendar.MONTH, i);
                months.add(dateFormat.format(cal.getTime()).toLowerCase());
            }
            monthMap.put(locale , months);
        }
    }

    @Override
    public int compare(Object month1, Object month2) {
        List months = monthMap.get(this.locale);
        if (months == null) {
            throw new NullPointerException("MonthNamesComparator cannot perform comparison - internal data is not initialized properly.");
        }
        return (months.indexOf(((String) month1).toLowerCase()) - months.indexOf(((String) month2).toLowerCase()));

    }
}

And simple test class to POC:

import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

/**
 *
 * @author akashtalyan
 */
public class TestMonths {
    public static void main(String[] args){
        Locale en = Locale.ENGLISH, ru = new Locale("ru","RU");
        String[] monthsToTestEn = new String[] {"FebRUary", "maY", "sepTember", "january", "december"};
        String[] monthsToTestRu = new String[] {"АпреЛь", "январь", "Март", "Август"};

        Map map = new TreeMap(new MonthNamesComparator(en));
        int i = 0;
        System.out.println("En Map original:");
        for (String month : monthsToTestEn) {
            System.out.print(month + " ");
            map.put(month, new StringBuilder(String.valueOf(++i)).append(" position in source array").toString());
        }
            System.out.println();
            System.out.println("En Map sorted:");
        for (String month : (Set<String>)map.keySet()) {
            System.out.println(month + " " + map.get(month));
        }
        i = 0;
        map = new TreeMap(new MonthNamesComparator(ru));
        System.out.println("Ru Map original:");
        for (String month : monthsToTestRu) {
            System.out.print(month + " ");
            map.put(month, new StringBuilder(String.valueOf(++i)).append(" position in source array").toString());
        }
            System.out.println();
        System.out.println("Ru Map sorted:");
        for (String month : (Set<String>)map.keySet()) {
            System.out.println(month + " " + map.get(month));
        }
    }

}

Enjoy it, works like a charm.

创建映射:

month_map = {"January":1,
             "February":2,
             "March":3,
             "April":4} # etc..

使用映射将一个月与另一个月进行比较。

大多数语言/框架都有用于处理日期的对象。创建所有月份的日期对象,并使用本机(如果可用)不等运算符或基本排序函数对它们进行比较:

import datetime
January  = datetime.date(2010,1,1)
February = datetime.date(2010,2,1)
if February < January: print("The world explodes.")

Create a mapping:

month_map = {"January":1,
             "February":2,
             "March":3,
             "April":4} # etc..

Use the mapping to compare one month to the other.

OR

Most languages/frameworks have objects for handling dates. Create date objects for all the months and compare them using the native (if available) inequality operators or basic sorting functions:

import datetime
January  = datetime.date(2010,1,1)
February = datetime.date(2010,2,1)
if February < January: print("The world explodes.")
丢了幸福的猪 2024-08-25 06:37:28

感谢大家的建议,我想将你们全部标记为已接受。

这是生成的代码:

// correct order 
months as String[] = ["jan", "feb", "mar", "apr", "may", "jun",
                      "jul", "aug", "sep", "oct", "nov", "dec"]
// my unsorted months 
myMonths as String[] = ["mar", "dec", "jul", "jan", "sep"]

// poor substitute for Map
mappedIndex as Int[]

// create an array with the corresponding index 
for each m in myMonths do
    i as Int = 0;
    for each month in months do 
       if m == month then 
           mappedIndex[] = i // no break, so I should use "else"
       else
          i = i + 1
       end
    end
end

// At this point mapped index has the same order as my "unsorted" array
// in this case [2,11,5,0,8]

// Fortunately this language has "sort" otherwise I would jump out of the window
mappedIndex.sort()

// create a new array to hold the sorted values
myMonthsSorted as String[]

// and fill it with the correct value
for each i in mappedIndex do 
   myMonthsSorted[] = months[i]
end

Thanks all for the suggestions, I would like to mark you all as accepted.

Here's the resulting code:

// correct order 
months as String[] = ["jan", "feb", "mar", "apr", "may", "jun",
                      "jul", "aug", "sep", "oct", "nov", "dec"]
// my unsorted months 
myMonths as String[] = ["mar", "dec", "jul", "jan", "sep"]

// poor substitute for Map
mappedIndex as Int[]

// create an array with the corresponding index 
for each m in myMonths do
    i as Int = 0;
    for each month in months do 
       if m == month then 
           mappedIndex[] = i // no break, so I should use "else"
       else
          i = i + 1
       end
    end
end

// At this point mapped index has the same order as my "unsorted" array
// in this case [2,11,5,0,8]

// Fortunately this language has "sort" otherwise I would jump out of the window
mappedIndex.sort()

// create a new array to hold the sorted values
myMonthsSorted as String[]

// and fill it with the correct value
for each i in mappedIndex do 
   myMonthsSorted[] = months[i]
end
许久 2024-08-25 06:37:28

对于像月份这样的东西,我只是硬编码我需要的数组......

var correctOrdering = {
    english: ["January", "February", "March", ...],
    french: ["Janvier", "Février", "Mars", ...],
    russian: ["Январь", "февраль", "март"],
    ...
};

月份名称不会很快改变。

For something like months, I'd just hard-code the arrays I needed...

var correctOrdering = {
    english: ["January", "February", "March", ...],
    french: ["Janvier", "Février", "Mars", ...],
    russian: ["Январь", "февраль", "март"],
    ...
};

It's not like month names are going to change any time soon.

暖心男生 2024-08-25 06:37:28

tl;dr

EnumSet.of( Month.JANUARY , Month.MARCH , Month.OCTOBER , Month.DECEMBER ).toString()

Enum

如果您的语言提供了强大的 enum 像 Java 一样方便,定义十几个对象。请参阅 Oracle 教程

java.time.Month

java.time 类包括方便的 Month 枚举,定义十几个对象,每个对象代表一年中的一月到十二月。

它们编号为 1-12,并按正确的顺序定义,从 1 月到 12 月。

在您的代码库中,使用此枚举的对象来替换任何单纯整数的使用或月份名称字符串的使用。在整个过程中使用 Month 对象可以提供类型安全,确保值有效,并使您的代码更加自文档化。

在 Java 中, EnumSet< /a> 和 EnumMap< /a> 是 Set地图 针对枚举值进行了优化。它们执行速度非常快并且占用的内存很少。

EnumSet<Month> months = EnumSet.of( Month.JANUARY , Month.MARCH , Month.OCTOBER , Month.DECEMBER );

EnumSet 按自然顺序(即声明枚举常量的顺序)进行迭代。因此无需显式排序您的集合。

该类包括 getDisplayName 方法,用于生成月份名称的本地化字符串。指定 TextStyle< /a> 您想要文本的长度或缩写。并为 (a) 翻译中使用的人类语言和 (b) 决定缩写、标点符号和大写等问题的文化规范指定一个 Locale

for( Month month : months ) {
    String output = month.getDisplayName( TextStyle.SHORT_STANDALONE , Locale.CANADA_FRENCH );  // Or Locale.US, Locale.ITALY, etc.
    System.out.println( output );
}

tl;dr

EnumSet.of( Month.JANUARY , Month.MARCH , Month.OCTOBER , Month.DECEMBER ).toString()

Enum

If your language provides a powerful enum facility as does Java, define a dozen objects. See Oracle Tutorial.

java.time.Month

The java.time classes include the handy Month enum, defining a dozen objects one for each month of the year January-December.

They are numbered 1-12, and defined in proper order, January to December.

In your code base, use objects of this enum to replace any use of mere integers or use of name-of-month strings. Using Month objects throughout provides type-safety, ensures valid values, and makes your code more self-documenting.

In Java, the EnumSet and EnumMap are implementations of Set and Map that are optimized for enum values. They execute very quickly and take very little memory.

EnumSet<Month> months = EnumSet.of( Month.JANUARY , Month.MARCH , Month.OCTOBER , Month.DECEMBER );

The EnumSet iterates in natural order, the order in which the enum constants are declared. So no need to explicitly sort your collection.

The class includes a getDisplayName method for generating a localized String of the name of the month. Specify a TextStyle for how long or abbreviated you want the text. And specify a Locale for (a) the human language to use in translation, and (b) the cultural norms to decide issues such as abbreviation, punctuation, and capitalization.

for( Month month : months ) {
    String output = month.getDisplayName( TextStyle.SHORT_STANDALONE , Locale.CANADA_FRENCH );  // Or Locale.US, Locale.ITALY, etc.
    System.out.println( output );
}
将军与妓 2024-08-25 06:37:28

为每个月添加前缀:


Jan -> aJan
Feb -> bFeb
...

排序,然后删除前缀。

Add a prefix for each month:


Jan -> aJan
Feb -> bFeb
...

Sort, then remove the prefix.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文