Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added ReverseArabicChars() that reverses only Arabic characters #11

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 66 additions & 7 deletions stringutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,61 @@ func Reverse(s string) string {
return string(r)
}

// ReverseArabicChars returns a string reversed
func ReverseArabicChars(s string) string {
s = Reverse(s)

var (
arabicChars = getNonArabicCharsRanges(s)
runes = []rune(s)
)

for _, c := range arabicChars {
after := runes[c.end+1:]
runes = append(runes[0:c.start], []rune(Reverse(string(runes[c.start:c.end+1])))...)
runes = append(runes, after...)
}

return string(runes)
}

type _range struct {
start, end int
}

// getNonArabicCharsRanges returns ranges of the string where non arabic characters exist!
func getNonArabicCharsRanges(s string) []_range {
var (
start, end = 0, 0
indexes = []_range{}
foundArabic = false
)

i := 0
for _, c := range s {
if !isArabicChar(c) {
if !foundArabic {
start = i
foundArabic = true
}
} else {
end = i - 1
if end > start {
indexes = append(indexes, _range{start, end})
}
start = i
foundArabic = false
}
i++
}

if len(indexes) == 0 || indexes[len(indexes)-1].end != len(s)-1 {
indexes = append(indexes, _range{start, i - 1})
}

return indexes
}

// SmartLength returns the length of the given string
// without considering the Arabic Vowels (Tashkeel).
func SmartLength(s *string) int {
Expand Down Expand Up @@ -139,18 +194,22 @@ func getHarf(char rune) Harf {
return Harf{Unicode: char, Isolated: char, Medium: char, Final: char}
}

// isArabicChar checks whether the character is from the arabic alphabet or not
func isArabicChar(chr rune) bool {
for _, c := range alphabet {
if c.equals(chr) {
return true
}
}
return false
}

//RemoveAllNonAlphabetChars deletes all characters which are not included in Arabic Alphabet
func RemoveAllNonArabicChars(text string) string {
runes := []rune(text)
newText := []rune{}
for _, current := range runes {
inAlphabet := false
for _, s := range alphabet {
if s.equals(current) {
inAlphabet = true
}
}
if inAlphabet {
if isArabicChar(current) {
newText = append(newText, current)
}
}
Expand Down
33 changes: 33 additions & 0 deletions stringutils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,36 @@ func TestRemoveAllNonArabicChars(t *testing.T) {
}
}
}

func eqArr(a1, a2 []_range) bool {
if len(a1) != len(a2) {
return false
}

for i := 0; i < len(a1); i++ {
if a1[i].start != a2[i].start && a1[i].end != a2[i].end {
return false
}
}

return true
}

func TestGetArabicCharsIndexes(t *testing.T) {
cases := []struct {
in, want string
}{
{"نص عربي", "يبرع صن"},
{"السلام عليكم", "مكيلع مالسلا"},
{"مرhبا يا friends اصدقاء", "ءاقدصا friends اي ابhرم"},
{"Hello World!", "Hello World!"},
}

for _, c := range cases {
out := ReverseArabicChars(c.in)
if out != c.want {
t.Errorf("getArabicCharsRanges(%s) == %s, want %s\n", c.in, out, c.want)
}
}

}