How to sort list by Persian alphabet?

Viewed 2343

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>

6 Answers

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>

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

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.

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

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

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>

Related