1

I want to search a word from an array of strings.

array = ["ram","gopal","varma","govind","ravan","alan"]

if my search text is goal i want to list as follows:

result = ["gopal","govind","alan"]

ie in gopal & goal only p is missing so it should be in search list with higher priority.

Is there any way to do such filtering?

vahdet
  • 6,357
  • 9
  • 51
  • 106
Nikhil Raj
  • 49
  • 8
  • you need single object or multiple object ? –  Feb 22 '19 at 08:16
  • Actually i want an array of items as shown in question. ie all items from that contains the subsequences of search text. but most similar word should show as first in list. – Nikhil Raj Feb 22 '19 at 08:51
  • There is an `a` in `"ram"` and others. Should the common subsequence at least have 2 characters? – ielyamani Feb 22 '19 at 11:20
  • array = ["ram","gopal","varma","govind","varma","ravan","gopal","ravan","alan"] what will be the output? of this array please share. –  Feb 22 '19 at 13:33
  • @Carpsen90 yes thats true. Am used above result just to show my priority. varma, ram, ravan also should be in list because of a in common. result = ["gopal","govind","alan"," varma", "ravan", "ram"] – Nikhil Raj Feb 23 '19 at 08:46
  • If any of the answers below solved your problem please mark it as accepted by clicking the check mark next to the answer. see: [How does accepting an answer work?](https://meta.stackexchange.com/a/5235) for more information – ielyamani Feb 25 '19 at 18:55

2 Answers2

0

You want to find longest common subsequences. I would suggest you to look at this excelent article on Ray Wenderlich's Swift Algorithm Club where you can find your solution with examples.

EDIT:

Then you have to iterate over your array and keep track of how long a subsequence is for each world (for example in dictionary). Then you have to sort your array by the subsequences lengths.

For example like this:

let array = ["ram", "gopal", "varma", "govind", "ravan", "alan"]
let searchTerm = "goal"

var dictionary: [String: Int] = [:]
for element in array {
    dictionary[element] = searchTerm.longestCommonSubsequence(element).count
}

let result = dictionary.sorted(by: { $0.1 > $1.1 }).map { $0.key }
kiwisip
  • 437
  • 1
  • 4
  • 12
  • yes. i can Longest common subsequence algorithms to find. but that is used for comparing 2 strings right? i have an array of 1000 of items, for that its difficult to do that. – Nikhil Raj Feb 23 '19 at 08:49
  • You have to iterate over your array and keep track of how long a subsequence is for each world (for example in dictionary). Then you have to sort your array by the subsequences lengths. – kiwisip Feb 23 '19 at 09:40
0

The longest common subsequence between two strings can be defined recursively as follows :

func lcs(_ str1: String, _ str2: String, _ i: String.Index, _ j: String.Index) -> Int 
{
    if (i == str1.startIndex || j == str2.startIndex) {
        return 0
    }

    let beforeI = str1.index(before: i)
    let beforeJ = str2.index(before: j)

    if str1[beforeI] == str2[beforeJ] {
        return 1 + lcs(str1, str2, beforeI, beforeJ)
    } else {
        return max(lcs(str1, str2, i, beforeJ), lcs(str1, str2, beforeI, j))
    }
}

You can find a complete explanation of how this dynamic programming algorithm works here.

So, given an array of strings and a search text :

let array = ["ram", "gopal", "varma", "govind", "ravan", "alan", "logan"]
let searchText = "goal"

We can associate a score to each element of the array, filter only those that have a non-zero score, sort them by score, and then only key the words from the tuples :

let result = array
    .map { ($0, lcs(searchText,
                    $0,
                    searchText.endIndex,
                    $0.endIndex)) }
    .filter { $0.1 > 0 }
    .sorted { $0.1 > $1.1 }
    .map { $0.0 }

print(result)

Which yields :

["gopal", "govind", "alan", "logan", "ram", "varma", "ravan"]

ielyamani
  • 17,807
  • 10
  • 55
  • 90