10

How can I read testArrray in ul li and sort this list?

lis.sort(function(a,b)) has English/Arabic/and alphabet support, not Persian alphabet support. Help me please. Thank you

var alphabets = ["ا", "ب", "پ", "ت", "ث", "ج", "چ", "ح", "خ", "د", "ذ", "ر", "ز", "ژ", "س", "ش", "ص", "ض", "ط", "ظ", "ع", "غ", "ف", "ق",
  "ک", "گ", "ل", "م", "ن", "و", "ه", "ی", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
];
var testArrray = ["ی", "گ", "ژ", "پ"];

var aChar;
var bChar;

function OrderFunc() {
  testArrray.sort(function(a, b) {
    return CharCompare(a, b, 0);
  });
  document.getElementById("result").innerHTML = testArrray;;
}

function CharCompare(a, b, index) {
  if (index == a.length || index == b.length)
    return 0;
    
  aChar = alphabets.indexOf(a.toUpperCase().charAt(index));
  bChar = alphabets.indexOf(b.toUpperCase().charAt(index));
  
  if (aChar != bChar)
    return aChar - bChar
  else
    return CharCompare(a, b, index + 1)
}
<html>
<head></head>
<body onload="OrderFunc()">
  <div id="result"></div>
  <ul class="myul">
    <li>ی</li>
    <li>پ</li>
    <li>گ</li>
    <li>ژ</li>
  </ul>
</body>
</html>
Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
ramin
  • 448
  • 4
  • 15

8 Answers8

10

String#localeCompare is supposed to be locale-aware and compare strings appropriately, so:

function OrderFunc() {
  // Get the list
  const ul = document.querySelector(".myul");
  // Get its items as an array
  const lis = [...ul.querySelectorAll("li")];
  // Sort the array with localeCompare
  lis.sort((a, b) => a.textContent.localeCompare(b.textContent));
  // Move each of them to the end of the list; this
  // puts them back in order
  for (const li of lis) {
    ul.appendChild(li);
  }
}

Live Example:

function OrderFunc() {
    // Get the list
    const ul = document.querySelector(".myul");
    // Get its items as an array
    const lis = [...ul.querySelectorAll("li")];
    // Sort the array with localeCompare
    lis.sort((a, b) => a.textContent.localeCompare(b.textContent));
    // Move each of them to the end of the list; this
    // puts them back in order
    for (const li of lis) {
        ul.appendChild(li);
    }
}
OrderFunc();
<div id="result"></div>
<ul class="myul">
<li>ی</li>
<li>پ</li>
<li>گ</li>
<li>ژ</li>
</ul>

You may need to pass some options to localeCompare, see the ECMAScript® Internationalization API Specification for more on that.


In a comment you asked:

What will i do first Persian and Second English Words?

If you're asking how to sort Persian words above English ones in the list, I think you'll probably have to detect what script the text is written in. You're supposed to be able to do that with a JavaScript regular expression, but the feature (Unicode property excapes) is new and not well-supported yet. You can use the XRegExp library to do it, though:

// This checks to see if the FULL string is in Arabic script; you'll
// probably have to adjust it to fix your use case
const rexArabic = XRegExp("^\\p{Arabic}+$");
function OrderFunc() {
    // Get the list
    const ul = document.querySelector(".myul");
    // Get its items as an array
    const lis = [...ul.querySelectorAll("li")];
    // Sort the array with localeCompare
    lis.sort(({textContent: a}, {textContent: b}) => {
        const aArabicScript = rexArabic.test(a);
        const bArabicScript = rexArabic.test(b);
        if (aArabicScript && !bArabicScript) {
            // `a` is in Arabic script, `b` isn't; `a` should be first
            return -1;
        }
        if (!aArabicScript && bArabicScript) {
            // `b` is in Arabic script, `a` isn't; `b` should be first
            return 1;
        }
        // They're in the same script
        return a.localeCompare(b);
    });
    // Move each of them to the end of the list; this
    // puts them back in order
    for (const li of lis) {
        ul.appendChild(li);
    }
}

Live Example:

// This checks to see if the FULL string is in Arabic script; you'll
// probably have to adjust it to fix your use case
const rexArabic = XRegExp("^\\p{Arabic}+$");
function OrderFunc() {
    // Get the list
    const ul = document.querySelector(".myul");
    // Get its items as an array
    const lis = [...ul.querySelectorAll("li")];
    // Sort the array with localeCompare
    lis.sort(({textContent: a}, {textContent: b}) => {
        const aArabicScript = rexArabic.test(a);
        const bArabicScript = rexArabic.test(b);
        if (aArabicScript && !bArabicScript) {
            // `a` is in Arabic script, `b` isn't; `a` should be first
            return -1;
        }
        if (!aArabicScript && bArabicScript) {
            // `b` is in Arabic script, `a` isn't; `b` should be first
            return 1;
        }
        // They're in the same script
        return a.localeCompare(b);
    });
    // Move each of them to the end of the list; this
    // puts them back in order
    for (const li of lis) {
        ul.appendChild(li);
    }
}
OrderFunc();
<div id="result"></div>
<ul class="myul">
<li>ی</li>
<li>پ</li>
<li>Some English</li>
<li>گ</li>
<li>More English</li>
<li>ژ</li>
</ul>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xregexp/3.2.0/xregexp-all.min.js"></script>
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • @ramin - Glad that helped! I should have said above: `[...ul.querySelectorAll("li")]` requires a browser where `NodeList` is iterable. Not all of them do that, but [see here](https://stackoverflow.com/a/46057817/157247) for how to make sure it is. – T.J. Crowder Jun 06 '19 at 09:36
9

To sort a list alphabetically in Persion, I used this code with <meta charset="utf-8"> and its result was perfect:

const myList = ["ی","گ","پ", "ژ"];
const collator = new Intl.Collator('fa');  
const sortedLetters = myList.sort(collator.compare);  
console.log(sortedLetters);

The Intl.Collator objects enable language sensitive string comparison.

For other languages, you can replace fa:

ar — Arabic
bg — Bulgarian
ca — Catalan
zh-Hans — Chinese, Han (Simplified variant)
cs — Czech
da — Danish
de — German
el — Modern Greek (1453 and later)
en — English
es — Spanish
fi — Finnish ,....

for more information please visit https://dev.to/aumayeung/comparing-non-english-strings-with-javascript-collators-57bf and https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Collator

Nasim B. D
  • 161
  • 1
  • 6
  • 1
    Question: Where did you find "fa" to be farsi for BCP-47 Language Tag? I can't seem to find it anywhere. – Moa Oct 27 '21 at 05:52
  • Please refer to the first reference I've mentioned: https://dev.to/aumayeung/comparing-non-english-strings-with-javascript-collators-57bf – Nasim B. D Oct 28 '21 at 12:40
  • So I see it in your list there, but what is the source that produced your BCP-47? All other lists I have found, (i.e. https://www.techonthenet.com/js/language_tags.php) do not have the "fa". I was just wondering where you got it from? – Moa Oct 29 '21 at 20:49
3

I never tested it and really cannot do it because I have no idea what letter comes before or after in arabic but I can point you to the right direction. You will need to use localeCompare in a way similiar to this:

arr.sort((x,y)=>x.localeCompare(y, 'ar-ma'))

ar-ma being Arabian Morocco language code which you should change to the language code of your needs.

Carlos Alves Jorge
  • 1,919
  • 1
  • 13
  • 29
  • Probably worth pointing out what the `ar-ma` string means. I'd have probably used `fa` and it seems to generate the same results. – James Long Jun 06 '19 at 09:26
2

I had same problem And I wrote this function , It works well for me .. so I decided to share it here for you :

// costome order of english and persian letters 
var persianAlphabets = [" ", "آ", "ا", "ب", "پ", "ت", "ث", "ج", "چ", "ح", "خ", "د", "ذ", "ر", "ز", "ژ", "س", "ش", "ص", "ض", "ط", "ظ", "ع", "غ", "ف", "ق", "ک", "گ", "ل", "م", "ن", "و", "ه", "ی", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"];

// function for sorting an array of persian words 
function customSort(x, y) {
  var i = 0;
  var maxLen = Math.min(x.length, y.length);

  function increseIndex() {
    if (persianAlphabets.indexOf(x[i]) == persianAlphabets.indexOf(y[i]) &&
      i <= maxLen) {
      i++;
      increseIndex();
    } else return
  }
  increseIndex();

  if (persianAlphabets.indexOf(x[i]) <
    persianAlphabets.indexOf(y[i])) {
    return -1;
  }
  if (persianAlphabets.indexOf(x[i]) >
    persianAlphabets.indexOf(y[i])) {
    return 1;
  }
  return 0;
}

// sample array for testing 
var testArrray = [
  "بابا",
  "آبادان",
  "آب",
  "احمد آقا",
  "احد محمدی",
  "احد مرادی",
  "یونس",
  "مادر 1",
  "آبادانی",
  "ش س",
  "شگیرا",
  "یدالله",
  "مادر 2",
  "سلام"
];

// applying the sorting function 
testArrray.sort(customSort);

// testing resoults 
console.log(testArrray);
1

Crowder gave the correct answer. But if you want to take matter in your own hands, you can apply your custom sorting function which sorts by comparing indexes in the reference array.

var alphabets = ["ا", "ب", "پ", "ت", "ث", "ج","چ","ح","خ","د","ذ","ر","ز","ژ","س","ش","ص","ض","ط","ظ","ع","غ","ف","ق","ک","گ","ل","م","ن","و","ه","ی","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];

var testArrray = ["ی","گ","ژ","پ"];
testArrray.sort(customSort(alphabets));
function customSort(alphabets){
    return function (x,y) {
      if (alphabets.indexOf(x) < alphabets.indexOf(y)) {
        return -1;
      }
      if (alphabets.indexOf(x) > alphabets.indexOf(y)) {
        return 1;
      }
      return 0;
  }
}
console.log(testArrray);
shreyas d
  • 774
  • 1
  • 4
  • 16
1

function OrderFunc() {
    // Get the list
    const ul = document.querySelector(".myul");
    // Get its items as an array
    const lis = [...ul.querySelectorAll("li")];
    // Sort the array with localeCompare
    lis.sort((a, b) => a.textContent.localeCompare(b.textContent));
    // Move each of them to the end of the list; this
    // puts them back in order
    for (const li of lis) {
        ul.appendChild(li);
    }
}
OrderFunc();
<div id="result"></div>
<ul class="myul">
<li>ی</li>
<li>پ</li>
<li>گ</li>
<li>ژ</li>
</ul>
1

I tested the code below and it worked for me. I hope this could help other people who are looking for a good and fast solution.

    const result = [ {code: 1, title: 'کارن'},
                     {code: 2, title: 'پیروز'},
                     {code: 3, title: 'ایران'}]    
    const sortedResult = result.sort((a,b)=> {
          return a.title.localeCompare(b.title, 'fa')
    )}
Mohammad Sadegh Panadgoo
  • 3,929
  • 1
  • 10
  • 12
0

This is my best working solution:

function PersianSort(words,target) {
    var els = $(words).get();
    els.sort(function(el1, el2){
        return $(el1).text().trim().localeCompare($(el2).text().trim())
    });
    $(target).append(els)
}
ul.container li {
   padding:5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<button onclick="PersianSort('.container li','.container')" type="button" value="1">Sort</button>
<ul class="container">
  <li>هستی</li>
  <li>گلی</li>
  <li>Reza</li>
  <li>چکامه</li>
  <li>Amir</li>
  <li>ویدا</li>
  <li>ژاله</li>
  <li>Ramin</li>
  <li>پوران</li>
  <li>یگانه</li>
  <li>آناهیتا</li>
  <li>آلاله</li>
</ul>
ramin
  • 448
  • 4
  • 15