7

私はこの月の配列を持っています:

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

そして、私はそれを次のようにソートしたいと思います:

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

私は現在、「if/else」の恐ろしいカスケードを考えていますが、これを行う他の方法があるのだろうか.

悪い点は、これを「文字列」でのみ行う必要があることです (つまり、Date オブジェクトなどを使用せずに)。

良いアプローチは何でしょうか?

4

10 に答える 10

12

カスタムの並べ替え順序を提供する方法があれば、正しい順序を定義するリストを作成します。

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

次に、そのリスト内の位置で並べ替えます。次のようになります。

toSort.sort(a, b) => compare(correct.index(a), correct.index(b))
于 2010-01-20T00:14:03.747 に答える
9

name->index でテーブルを作成し、テーブル内の値に基づいて配列をソートします。

arr.sort(myCompare)C# 、 Java Collections.sort(arr, myCompare)、 Python arr.sort(myCompare)、 PHP usort($arr, 'myCompare')、 C++ で、いくつかの例が役立つ場合がありますsort(vec.begin(), vec.end(), myCompare)

于 2010-01-20T00:04:49.230 に答える
4

適切な並べ替えの配列を用意し、それに基づいて並べ替えます。

別の解決策 (言語でサポートされている場合) は、月名から数字 (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

于 2010-01-20T00:04:09.357 に答える
1

Java POV から話して、私は (私がよくするように) google-collections (すぐにGuavaに置き換えられます) をポン引きします:

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

...これで完了です。

他の誰かが作成した場合は、自分で作成しないでください。おそらく、あなたよりも効率的で優れた API を使用しています。

一般的なケースでは役に立ちませんが、Java 関係者が同じ問題を抱えている場合に備えて...

于 2010-01-20T03:19:34.210 に答える
1

同僚、

問題/ビジネス上の問題が 2 年以上続いているようです。月の名前 (文字列として格納されている) を適切に並べ替えるためのコンパレータを作成することにしました。また、目的のロケールの月の名前も保持します ============== 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()));

    }
}

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));
        }
    }

}

それをお楽しみください、魅力のように機能します。

于 2012-05-22T15:22:51.053 に答える
0

tl;dr

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

列挙型

あなたの言語が Java のように強力なenum機能を提供している場合は、多数のオブジェクトを定義してください。Oracle チュートリアルを参照してください。

java.time.Month

java.timeクラスには便利なenum が含まれておりMonth、1 月から 12 月までの各月に 1 つずつ、12 個のオブジェクトを定義しています。

それらには 1 ~ 12 の番号が付けられ、1 月から 12 月までの適切な順序で定義されます。

コード ベースでは、この列挙型のオブジェクトを使用して、単なる整数の使用または月名文字列の使用を置き換えます。全体でオブジェクトを使用Monthすると、タイプ セーフが提供され、有効な値が保証され、コードがより自己文書化されます。

Java では、EnumSetとは列挙値用に最適化されたとEnumMapの実装です。それらは非常に高速に実行され、ほとんどメモリを消費しません。SetMap

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

EnumSet、列挙型定数が宣言された順序である自然な順序で反復します。したがって、コレクションを明示的にソートする必要はありません。

このクラスにはgetDisplayName、月の名前のローカライズされた文字列を生成するメソッドが含まれています。テキストの長さまたは省略形を指定TextStyleします。そしてLocale、(a) 翻訳で使用する人間の言語、および (b) 省略形、句読点、大文字化などの問題を決定するための文化的規範の を指定します。

for( Month month : months ) {
    String output = month.getDisplayName( TextStyle.SHORT_STANDALONE , Locale.CANADA_FRENCH );  // Or Locale.US, Locale.ITALY, etc.
    System.out.println( output );
}
于 2016-08-31T02:13:20.297 に答える
0

マッピングを作成します。

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.")
于 2010-01-20T00:40:56.820 に答える
0

すべての提案に感謝します。すべてを承認済みとしてマークしたいと思います。

結果のコードは次のとおりです。

// 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
于 2010-01-20T00:49:13.807 に答える
0

数か月間、必要な配列をハードコードするだけでした...

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

月の名前がす​​ぐに変更されるわけではありません。

于 2010-01-20T00:06:25.563 に答える
-1

各月のプレフィックスを追加します。


Jan -> aJan
Feb -> bFeb
...

並べ替えてから、プレフィックスを削除します。

于 2010-01-20T00:16:18.800 に答える