Jump to content
php.lv forumi

JavaScript LocaleCompare latviešu valodai


Gagarin

Recommended Posts

Sveiki,
Taisu mājas lapu uz Eleventy un saskaros problēmu: localeCompare kļūdās(?) šķirojot virsrakstus latviešu valodā.
Piemērs ar "sašķirotu" sarakstu:
1. Egles zarā sēž kaķis
2. Ēna
3. Epizode
4. Ērenpress ir velosipēdu ražotājs
5. Ēvele

Kā redzams vārds "Ēna", kas ir ar garo "ē" pamanās būt virs vārda "Epizode". Nojaušu tas ir otrā burta dēļ, t.i. vārdā "Ēna" burts "n" alfabētiski ir pēc burta "p" (Epizode). LocaleCompare it kā nesaprot, ka burts ar garumzīmi ir pilntiesīgs loceklis alfabētā, jo garumzīme netiek ņemta vērā, bet gan vārda otrais burts šķirojot doto sarakstu.

Kods virsrakstu šķirošanai:

  eleventyConfig.addCollection("postsDescending", function (collection) {
    const posts = collection
      .getFilteredByGlob("src/posts/*.md")
      .sort(function (a, b) {
        return a.data?.title.localeCompare(b.data?.title, "lv-LV", {
          caseFirst: false,
          sensitivity: "variant",
          ignorePunctuation: true,
          usage: "sort",
        });
      });
    return posts;
  });

Vai kāds ir izmantojis LocaleCompare priekš šķirošanas latviešu valodā?

tOaMmJTWta.png

Edited by Gagarin
Link to comment
Share on other sites

2 hours ago, briedis said:

Šis *ūds nestrādās. Ko es iesaku darīt ir, nodefinē stringu ar visu alfabētu, taisi custom sort metodi, kas sasortē skatoties pēc burta indeksa stringā. a - 0, ā-1 utt.

Pateicos par iesaisti!
Tomēr kaut ko daru ne tā kā pienākas, jo virsraksti ir tikai daļēji alfabēta secībā (skat. ekrānšāviņu). Labā ziņa, ka ar šo vismaz virsraksts, kura sākumburts "Ē" atrodas aiz virsraksta, kas sākas ar "E" .. Nesaprotu kā sasaistīt definēto alfabētu ar virsrakstiem. Vari, lūdzu, iedot vēl kādu padomu?

  eleventyConfig.addCollection("postsDescending", function (collection) {
    const alphabet = ['A','a','Ā','ā','B','b','C','c','Č','č','D','d','E','e','Ē','ē','F','f','G','g','Ģ','ģ','H','h','I','i','Ī','ī','J','j','K','k','Ķ','ķ','L','l','Ļ','ļ','M','m','N','n','Ņ','ņ','O','o','P','p','R','r','S','s','Š','š','T','t','U','u','Ū','ū','V','v','Z','z','Ž','ž'];
    const posts = collection
      .getFilteredByGlob("src/posts/*.md")
      .sort(function (a, b) {
        var titleA = a.data?.title, titleB = b.data?.title;
          if (alphabet.titleA < alphabet.titleB) {
              return -1;
          }
          if (alphabet.titleA > alphabet.titleB) {
              return 1;
          }
          return 0
      });
    return posts;
  });

 

gimplseofcontent.png

Link to comment
Share on other sites

Man liekas, ka problēma šeit ir, ka mēģini atņemt visu virsrakstu no virsraksta. Neesmu drošs, vai tā var darīt. Visdrīzāk ir jāiet cauri pēc tam katram virsraksta burtam un jāsalīdzina tie individuāli, kamēr kāds no tiem atškirās titleA[i] - titleB[i].

Link to comment
Share on other sites

const arr = [ 'Ēnas', 'Ēna', 'Epizode', 'Ēvele', 'Egles zarā sēž kaķis', 'Ērenpress ir velosipēdu ražotājs']

 const alphabet = ['A','a','Ā','ā','B','b','C','c','Č','č','D','d','E','e','Ē','ē','F','f','G','g','Ģ','ģ','H','h','I','i','Ī','ī','J','j','K','k','Ķ','ķ','L','l','Ļ','ļ','M','m','N','n','Ņ','ņ','O','o','P','p','R','r','S','s','Š','š','T','t','U','u','Ū','ū','V','v','Z','z','Ž','ž'];

arr.sort(function (a, b) {
          // index = burta pozīcija (0,1,2,3)...
          const byLetters = (index) => {
            // paņemam burtu pēc indexa (piemēram Ē, n, a, s)
            const titleA = a[index], titleB = b[index];
            
            // ja kāds no burtiem vairs nav (ēna/ēnas gadījuma), īsāko vārdu liekam priekšā
            if (!titleA || !titleB) {
              return titleA ? 1 : -1
            }
            
            // ja burti ir vienādi, skatāmies nākamo burtu
            if (titleA === titleB) {
              return byLetters(index+1)
            }
 
            // salīdzinam pēc alfabēta
            const indexA = alphabet.findIndex(c => c === titleA)
            const indexB= alphabet.findIndex(c => c === titleB)
            if (indexA < indexB) {
                return -1;
            }
            if (indexA > indexB) {
                return 1;
            }
          }
          
          // sākam ar pirmo (0) burtu vārdā
          return byLetters(0)          
});

Lielākā kļūdas tavā kodā:

1. nav tāds `alphabet.titleA`, 

alphabet.titleA < alphabet.titleB
Edited by jurgenzz
Link to comment
Share on other sites

9 hours ago, jurgenzz said:




const arr = [ 'Ēnas', 'Ēna', 'Epizode', 'Ēvele', 'Egles zarā sēž kaķis', 'Ērenpress ir velosipēdu ražotājs']

 const alphabet = ['A','a','Ā','ā','B','b','C','c','Č','č','D','d','E','e','Ē','ē','F','f','G','g','Ģ','ģ','H','h','I','i','Ī','ī','J','j','K','k','Ķ','ķ','L','l','Ļ','ļ','M','m','N','n','Ņ','ņ','O','o','P','p','R','r','S','s','Š','š','T','t','U','u','Ū','ū','V','v','Z','z','Ž','ž'];

arr.sort(function (a, b) {
          // index = burta pozīcija (0,1,2,3)...
          const byLetters = (index) => {
            // paņemam burtu pēc indexa (piemēram Ē, n, a, s)
            const titleA = a[index], titleB = b[index];
            
            // ja kāds no burtiem vairs nav (ēna/ēnas gadījuma), īsāko vārdu liekam priekšā
            if (!titleA || !titleB) {
              return titleA ? 1 : -1
            }
            
            // ja burti ir vienādi, skatāmies nākamo burtu
            if (titleA === titleB) {
              return byLetters(index+1)
            }
 
            // salīdzinam pēc alfabēta
            const indexA = alphabet.findIndex(c => c === titleA)
            const indexB= alphabet.findIndex(c => c === titleB)
            if (indexA < indexB) {
                return -1;
            }
            if (indexA > indexB) {
                return 1;
            }
          }
          
          // sākam ar pirmo (0) burtu vārdā
          return byLetters(0)          
});

Lielākā kļūdas tavā kodā:

1. nav tāds `alphabet.titleA`, 





alphabet.titleA < alphabet.titleB

Liels paldies par atsaucību! Ceru kādam vēl skaistais kods noderēs!
Priekš Eleventy:

  eleventyConfig.addCollection("postsDescending", function (collection) {
    	const alphabet = ['A','a','Ā','ā','B','b','C','c','Č','č','D','d','E','e','Ē','ē','F','f','G','g','Ģ','ģ','H','h','I','i','Ī','ī','J','j','K','k','Ķ','ķ','L','l','Ļ','ļ','M','m','N','n','Ņ','ņ','O','o','P','p','R','r','S','s','Š','š','T','t','U','u','Ū','ū','V','v','Z','z','Ž','ž'];
		return collection.getFilteredByGlob("src/posts/*.md").sort(function (a, b) {
          const byLetters = (index) => {
            const titleA = a.data.title[index], titleB = b.data.title[index];
            if (!titleA || !titleB) {
              return titleA ? 1 : -1;
            }
            if (titleA === titleB) {
              return byLetters(index+1);
            }
            const indexA = alphabet.findIndex(c => c === titleA);
            const indexB = alphabet.findIndex(c => c === titleB);
            if (indexA < indexB) {
                return -1;
            }
            if (indexA > indexB) {
                return 1;
            }
          }
          return byLetters(0);      
        });
    });

 

Edited by Gagarin
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...