teratail header banner
teratail header banner
質問するログイン新規登録
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

1回答

625閲覧

TinySortで数字を自然な順番で並び替えしたい

agepan

総合スコア66

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

0クリップ

投稿2018/11/30 10:06

0

0

HTMLのliタグを文字列によって並び替えることができるTinySortを使用しております。
これを使うと例えば下記のような並びがあったとき、

HTML

1<ul> 2 <li>ZZZ</li> 3 <li>AAA</li> 4 <li>DDD</li> 5</ul> 6 7<!--並び替えを実行すると↓--> 8 9<ul> 10 <li>AAA</li> 11 <li>DDD</li> 12 <li>ZZZ</li> 13</ul>

という具合に50音順で並び替えることができます。
ところが下記のリストを並び替えようとしてもうまく並び替えてくれません。

HTML

1<ul> 2 <li>9月</li> 3 <li>8月</li> 4 <li>10月</li> 5</ul> 6 7<!--並び替えを実行すると↓--> 8 9<ul> 10 <li>10月</li> 11 <li>8月</li> 12 <li>9月</li> 13</ul>

TinySortのページの「sorted numbers」(=ソートされた数字)項目を参照するに、1桁数字も2桁数字も自然な並びになるように並び替えてくれるようですが、上記「10月」などのように後ろに文字が付くと、0〜9の並びを機械的に判断して並び替えてしまうようです。

これを「8月」「9月」「10月」と並び替えられるようにしたいのですが、どういじったらいいものか見当がつきません。

TinySortのオプションにある「options.natural」(自然なソート順)をtrueにしてみましたが変わりませんでした。またtinysort.charorder.js内にある下記コード部分の一番下の行、ここが並び替えの順序を指定している気がするところで、試しに「0-9」「0-999」などと入れてみましたが全く変わりませんでした。

上記お分かりになる方がいらっしゃいましたらお知恵拝借させていただければと思います。

JavaScript

1 var fromCharCode = String.fromCharCode // minify placeholder 2 ,mathmn = Math.min // minify placeholder 3 ,nll = null // minify placeholder 4 ,fnIndexOf = Array.prototype.indexOf// minify placeholder 5 ,plugin = tinysort.plugin 6 ,loop = plugin.loop 7 // 8 ,charOrder // equals the input oSettings.charOrder so we can test any changes 9 ,allCharsList = (function(a){ // all latin chars 32-255 10 // using lowerCase instead of upperCase so _ will sort before 11 for (var i=32,s=fromCharCode(i),len=255;i<len;i++,s=fromCharCode(i).toLowerCase()) { 12 if (fnIndexOf.call(a,s)===-1) a.push(s); 13 } 14 return a.sort(); 15 })([]) 16 ,orderedCharlist // similar to sAllChars but with the changed char order 17 ,replacementIndex = 0x2500 // doubles are replaced with Unicode char starting at 0x2500 18 ,replacements = {} // replacement object // todo: reset? 19 ,regexNonLatin = /[^a-zA-Z]/g // ← 並び替え順序を指定していると思われる箇所 20

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

optionとしてsortFunctionを指定できるようなので、月を消して数値化して比較するような関数を渡せばできると思います

まず↓でテストしてみてください(chromeでF12を押してconsoleで実行するなど)

javascript

1const comparer = (a,b) => { 2 const numA = Number(a.replace(/[^\d]/g, '')); 3 const numB = Number(b.replace(/[^\d]/g, '')); 4 return numA - numB; 5} 6console.log(["2月","10月","9月","8月","12月"].sort(comparer)); 7console.log(["第2回目","第10回目","第9回目","第8回目","第12回目"].sort(comparer)); 8console.log(["A2","A10","A9","A8","A12"].sort(comparer));

納得できたら、↓こういう感じに書いてください

javascript

1tinysort('ul#xcst>li',{sortFunction:function(a,b) { 2 const numA = Number(a.replace(/[^\d]/g, '')); 3 const numB = Number(b.replace(/[^\d]/g, '')); 4 return numA - numB; 5}});

追加
要件が違うらしいので、とりあえずtinysortにかますまえに、検証用にサンプル関数を書いてみます。

javascript

1const comparer = (a,b) => { 2 const reg = /^([^\d]*)(\d+)(.*)$/; 3 const paramA = a.match(reg).slice(1,4); 4 const paramB = b.match(reg).slice(1,4); 5 console.log(paramA); 6 console.log(paramB); 7 8 if(paramA[0] !== paramB[0]) { return stringComparer(paramA[0], paramB[0]); } 9 const numA = Number(paramA[1]); 10 const numB = Number(paramB[1]); 11 if(numA !== numB) { return numA - numB; } 12 console.log("2"); 13 14 return stringComparer(paramA[2], paramB[2]);; 15} 16const stringComparer = (a, b) => { 17 if (a < b) { return -1; } 18 if (a > b) { return 1; } 19 return 0; 20} 21console.log(["2月","10月","9月","8月","12月"].sort(comparer)); 22console.log(["第2回目","第10回目","第9回目","第8回目","第12回目"].sort(comparer)); 23console.log(["A2","A10","A9","A8","A12"].sort(comparer)); 24console.log(["2月","10月","第3回目","ABC999の9", "ABC999の0","BBB31","1月"].sort(comparer));

この例では、AAA999の8とaaa999の7とAAA999の6が大文字小文字を無視して並ぶようにはなりません。いずれにしても明確な仕様を作ってもらわないことにはコードはかけません。
また、関数を使えばこういうことができる、というのが私の回答ですので、どういう関数を作るかは質問者様の仕様と技術でカバーしてください(仕様を提示してこのコード書いてというなら作業委託してください)

投稿2018/11/30 10:19

編集2018/12/07 02:26
papinianus

総合スコア12705

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

agepan

2018/11/30 10:26

ご回答ありがとうございます。 並び替えようとしているデータというのが特定の文字列ではなく、まったくバラバラな文字列になります。例えば「8月, 9月, 10月」かもしれませんし、「A1, A2, A10」かも、「○○○10回目」といったような文字列も考えられます。 そのため数字の1桁2桁3桁というのをきちっとTinySort側で認識して並び替えてもらう処理が必要になってくると思いますが、これはsortFunctionで賄えそうでしょうか?
papinianus

2018/11/30 10:37

正規表現で数値部分を切り出すとできると思います。特に○○○10回といった中置形式は設定でどうにかなるレベルではないのでなおさら関数を書くしかないです
papinianus

2018/11/30 10:38

数値のブロックが2つにはならないですよね?12A2とかは辛いと思います。
papinianus

2018/11/30 11:24

サンプルコード書きましたんで、試してみてください
agepan

2018/12/07 01:09

お返事遅くなりまして申し訳ございません、テストしてみました。 正しく数字の通りに並び替えができました! 実現させたいことはこれをさらにもう一歩踏み込んだ部分でして、この数字通りの並びをさせることに加えて、かつ50音で並べさせたいというものであります。 例えば以下の配列があったとき、 ["2月","10月","第3回目","ABC999の9", "ABC999の0","BBB31","1月"] このような結果になることが望ましいです。 ["1月", "2月","10月", "ABC999の0", "ABC999の9", "BBB31", "第3回目"] まず50音でソートし、次にそれを今回のコードのように数値でソートさせると良いかと思いましたが、そうすると50音でなくなってしまうので、どうしたら解決できるかなと難儀してるところです。
papinianus

2018/12/07 02:23

・2つの数字ブロックについて 少し前に書いたように数値が2つある場合(ABC999の9、みたいなパターン)では、サンプルで書いたコードは意図した数値にならないと思います。例えば、ABC0の9は10月より前に来ます。BBB1000というものがあったとして、ABC999の9のほうが後にきます。 ・望ましい結果 望ましい結果が、言葉で説明するとどういうソートになっているのか、分かりません。個人的には、忖度はできますが、機械は忖度してくれないので、人間系の推測に頼るような並びは仕様にならないのではないかという気がします。 多段階であってもよいので、仕様を言葉で、●なら×みたいな、判定できるルールで宣言してください。 (いちおう今回の例と望ましい結果になるようなものは今から回答に追記しておきます)
Lhankor_Mhy

2018/12/07 02:24

横からすみません。 ["ABC99ノ91", "ABC999の1", "ABC9991", "AB999Cの2"] ↑これはどのようにソートしたいですか?
papinianus

2018/12/07 02:30 編集

さすがの例ですけども、そんなん無理やわ、もう回答の範囲越えとるわ…(追記した例では、大文字小文字すら考慮していないというのに…) 上にもかきましたが、regexで[^\d]を消すっていうのは、あくまで例のための、安直なパターンなんで実用には耐えないと思ってます
Lhankor_Mhy

2018/12/07 02:32

ですよね。さすがにこの質問の後出しは、よくないと感じています。 コメントが前後してしまいましたが、先ほどのコメントは質問者に仕様を考えていただくためのものですので、お答えくださいね→質問者様
papinianus

2018/12/07 02:34

コメントに+したいです!
Lhankor_Mhy

2018/12/07 02:35

そのほか、小数とか指数表現とか16進数とか、考えるべきは色々ありすぎる……
papinianus

2018/12/07 02:38

きびしい ><
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.30%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問