Michele Riva
Senior Software Architect @NearForm
Google Developer Expert
Microsoft MVP
MicheleRivaCode
MicheleRivaCode
MicheleRivaCode
MicheleRivaCode
What I cannot create, I do not understand
Richard Feynman
MicheleRivaCode
MicheleRivaCode
MicheleRivaCode
MicheleRivaCode
MicheleRivaCode
sybase.com
Full-text search is a more advanced way to search a database.
Full-text search quickly finds all instances of a term (word) in a table without having to scan rows and without having to know which column a term is stored in.
Full-text search works by using text indexes.
A text index stores positional information for all terms found in the columns you create the text index on.
MicheleRivaCode
sybase.com
Full-text search is a more advanced way to search a database.
Full-text search quickly finds all instances of a term (word) in a table without having to scan rows and without having to know which column a term is stored in.
Full-text search works by using text indexes.
A text index stores positional information for all terms found in the columns you create the text index on.
MicheleRivaCode
sybase.com
Full-text search is a more advanced way to search a database.
Full-text search quickly finds all instances of a term (word) in a table without having to scan rows and without having to know which column a term is stored in.
Full-text search works by using text indexes.
A text index stores positional information for all terms found in the columns you create the text index on.
MicheleRivaCode
sybase.com
Full-text search is a more advanced way to search a database.
Full-text search quickly finds all instances of a term (word) in a table without having to scan rows and without having to know which column a term is stored in.
Full-text search works by using text indexes.
A text index stores positional information for all terms found in the columns you create the text index on.
MicheleRivaCode
MicheleRivaCode
Sonic
Meilisearch
MicheleRivaCode
Lunr.js
MiniSearch
Fuse.js
MicheleRivaCode
MicheleRivaCode
Understand what kind of data we want to store and retrieve
MicheleRivaCode
[
{
"id": 1,
"quote": "It's alive! It's alive!",
"movie": "Frankenstein",
"year": 1931
},
{
"id": 2,
"quote": "You've got to ask yourself one question: 'Do I feel lucky?' Well, do ya, punk?",
"movie": "Dirty Harry",
"year": 1971
},
{
"id": 3,
"quote": "Mama always said life was like a box of chocolates. You never know what you're gonna get.",
"movie": "Forrest Gump",
"year": 1994
}
]
MicheleRivaCode
// "It's alive! It's alive!"
["Its", "alive", "Its", "alive"]
// "You've got to ask yourself one question: 'Do I feel lucky?' Well, do ya, punk?"
[
"Youve", "got", "to", "ask", "yourself", "one", "question",
"Do", "I", "feel", "lucky", "Well", "do", "ya", "punk"
]
// "Mama always said life was like a box of chocolates. You never know what you're gonna get."
[
"Mama", "always", "said", "life", "was", "like", "a", "box", "of",
"chocolates", "You", "never", "know", "what", "youre", "gonna", "get"
]
Break the sentences into individual tokens
MicheleRivaCode
// "It's alive! It's alive!"
["its", "alive", "its", "alive"]
// "You've got to ask yourself one question: 'Do I feel lucky?' Well, do ya, punk?"
[
"youve", "got", "to", "ask", "yourself", "one", "question",
"do", "i", "feel", "lucky", "well", "do", "ya", "punk"
]
// "Mama always said life was like a box of chocolates. You never know what you're gonna get."
[
"mama", "always", "said", "life", "was", "like", "a", "box", "of",
"chocolates", "you", "never", "know", "what", "youre", "gonna", "get"
]
Lowercase all tokens
MicheleRivaCode
// "It's alive! It's alive!"
["its", "alive"]
// "You've got to ask yourself one question: 'Do I feel lucky?' Well, do ya, punk?"
[
"youve", "got", "to", "ask", "yourself", "one", "question",
"do", "i", "feel", "lucky", "well", "ya", "punk"
]
// "Mama always said life was like a box of chocolates. You never know what you're gonna get."
[
"mama", "always", "said", "life", "was", "like", "a", "box", "of",
"chocolates", "you", "never", "know", "what", "youre", "gonna", "get"
]
Remove duplicates
MicheleRivaCode
// "It's alive! It's alive!"
["alive"]
// "You've got to ask yourself one question: 'Do I feel lucky?' Well, do ya, punk?"
[
"youve", /* "got", */ /* "to", */ "ask", "yourself", "one", "question",
/* "do", */ /* "i", */ "feel", "lucky", "well", "ya", "punk"
]
// "Mama always said life was like a box of chocolates. You never know what you're gonna get."
[
"mama", "always", "said", "life", /* "was", */, "like", /* "a", */ "box", /* "of", */
"chocolates", "you", "never", "know", /* "what", */ "youre", /* "gonna", */ "get"
]
Remove stop-words*
MicheleRivaCode
Stop words are a set of commonly used words in a language. Examples of stop words in English are “a”, “the”, “is”, “are” and etc. Stop words are commonly used in Text Mining and Natural Language Processing (NLP) to eliminate words that are so commonly used that they carry very little useful information.
https://www.opinosis-analytics.com/knowledge-base/stop-words-explained/
MicheleRivaCode
// "It's alive! It's alive!"
["alive"]
// "You've got to ask yourself one question: 'Do I feel lucky?' Well, do ya, punk?"
[
"youve", /* "got", */ /* "to", */ "ask", "yourself", "one", "question",
/* "do", */ /* "i", */ "feel", "lucky", "well", "ya", "punk"
]
// "Mama always said life was like a box of chocolates. You never know what you're gonna get."
[
"mama", "always", "said", "life", /* "was", */, "like", /* "a", */ "box", /* "of", */
"chocolates", "you", "never", "know", /* "what", */ "youre", /* "gonna", */ "get"
]
Remove stop-words*
MicheleRivaCode
// "It's alive! It's alive!"
["alive"]
// "You've got to ask yourself one question: 'Do I feel lucky?' Well, do ya, punk?"
[
"you" /* was "youve" */, "ask", "yourself", "one", "question",
"feel", "luck" /* was "lucky" */, "well", /* "ya" becomes "you", duplicate */ "punk"
]
// "Mama always said life was like a box of chocolates. You never know what you're gonna get."
[
"mom" /* was "mama" */, "always", "say" /* was "said" */, "life", "like", "box",
"chocolate" /* was "chocolates" */, "you", "never", "know", /*"you", was "youre", duplicate */, "get"
]
Stemming*
MicheleRivaCode
Snowball
https://snowballstem.org
MicheleRivaCode
http://snowball.tartarus.org/algorithms/english/stemmer.html
MicheleRivaCode
http://snowball.tartarus.org/algorithms/german/stemmer.html
MicheleRivaCode
http://snowball.tartarus.org/algorithms/italian/stemmer.html
MicheleRivaCode
http://snowball.tartarus.org/algorithms/finnish/stemmer.html
MicheleRivaCode
MicheleRivaCode
[
{
"id": 1,
"quote": ["alive"],
...
},
{
"id": 2,
"quote": ["you", "ask", "yourself", "one", "question", "feel", "luck", "well", "punk"],
...
},
{
"id": 3,
"quote": ["mom", "always", "say", "life", "like", "box", "chocolate", "you", "never", "know", "get"],
...
}
]
Remaining tokens
MicheleRivaCode
MicheleRivaCode
MicheleRivaCode
MicheleRivaCode
Find document containing the word "chocolate" in linear time
MicheleRivaCode
Find document containing the word "chocolate" in linear time
MicheleRivaCode
Find document containing the word "chocolate" in linear time
MicheleRivaCode
Find document containing the word "chocolate" in linear time
MicheleRivaCode
Find document containing the word "chocolate" in linear time
MicheleRivaCode
Find document containing the word "chocolate" in linear time
MicheleRivaCode
Find document containing the word "chocolate" in linear time
MicheleRivaCode
MicheleRivaCode
MicheleRivaCode
animal = dog
book = algorithms to live by
color = green
language = javascript
city = florence
food = chocolate
MicheleRivaCode
MicheleRivaCode
MicheleRivaCode
MicheleRivaCode
MicheleRivaCode
MicheleRivaCode
MicheleRivaCode
function hash(key: string, size: number): number {
let hash = 0;
for (let i = 0; i < key.length; i++) {
let char = key[i];
hash = (hash << 5) + char.charCodeAt(0);
hash = (hash & hash) % size;
}
return hash;
}
Example of an hashing algorithm
MicheleRivaCode
function hash(key: string, size: number): number {
let hash = 0;
for (let i = 0; i < key.length; i++) {
let char = key[i];
hash = (hash << 5) + char.charCodeAt(0);
hash = (hash & hash) % size;
}
return hash;
}
const size = 10;
hash("food", size); // => 2
hash("book", size); // => 7
hash("hello, Berlin!", size); // => 9
Example of an hashing algorithm
MicheleRivaCode
Hence, time complexity is O(1)
MicheleRivaCode
MicheleRivaCode
MicheleRivaCode
But that's not enough to find "chocolate" inside of our array of documents in O(1)
MicheleRivaCode
MicheleRivaCode
{
1 => ["alive"],
2 => ["you", "ask", "yourself", "one", "question", "feel", "luck", "well", "punk"],
3 => ["mom", "always", "say", "life", "like", "box", "chocolate", "you", "never", "know", "get"],
}
Regular HashMap
MicheleRivaCode
{
"alive" => [1],
"you" => [2, 3],
"ask" => [1],
"yourself" => [2],
"chocolate" => [3],
"punk" => [2],
"one" => [2],
"question" => [2],
"feel" => [2],
"mom" => [3],
"always" => [3],
"say" => [3],
"know" => [3],
"luck" => [2],
"life" => [3],
"like" => [3],
"well" => [2],
"box" => [3],
"never" => [3],
"get" => [3]
}
Inverted Index
MicheleRivaCode
MicheleRivaCode
{
"intersect" => [10,32,12,2,3],
"interstellar" => [2,6,20,23,42],
"intergalactic" => [12,3,54,29,32],
"international" => [32,12,34,64,2],
"intervene" => [92,12,42,54,6],
"internal" => [102,32,543,6,1],
"telecommunication" => [91,2,4,23],
"television" => [10,8,6,15,3,2],
"telephone" => [1,85,14,54,76]
}
Many tokens are sharing a common prefix
MicheleRivaCode
MicheleRivaCode
MicheleRivaCode
MicheleRivaCode
Private
Primark
Prime
Primate
MicheleRivaCode
MicheleRivaCode
MicheleRivaCode
MicheleRivaCode
MicheleRivaCode
MicheleRivaCode
MicheleRivaCode
We can use a prefix tree as an "inverted index" to store the reference of a token with the document
MicheleRivaCode
"primark" => [1, 3] "primate" => [2, 4] "prime" => [1, 5] "private" => [2, 6] "art" => [4, 5] "artist" => [4, 7]
MicheleRivaCode
"primark" => [1, 3] "primate" => [2, 4] "prime" => [1, 5] "private" => [2, 6] "art" => [4, 5] "artist" => [4, 7]
MicheleRivaCode
"Talk is cheap! Show me the code!"
MicheleRivaCode
type Nullable<T> = T | null;
type Children = Map<string, TrieNode>;
type Docs = Set<string>;
type NodeContent = [string, Docs];
interface ITrieNode {
key: string;
parent: Nullable<TrieNode>;
children: Nullable<Children>;
docs: Docs;
end: boolean;
getWord: () => NodeContent;
removeDoc: (id: string) => boolean;
}
trieNode.ts
MicheleRivaCode
type FindResult = {
[key: string]: Set<string>;
}
interface ITrie {
root: TrieNode;
insert: (word: string, docId: string) => void;
contains: (word: string) => boolean;
find: (prefix: string) => FindResult;
removeDocByWord: (word: string, docId: string) => boolean;
remove: (word: string) => boolean;
}
trie.ts
MicheleRivaCode
class TrieNode implements ITrieNode {
public key;
public parent = null;
public children = new Map();
public docs = new Set();
public end = false;
}
trieNode.ts
MicheleRivaCode
class TrieNode implements ITrieNode {
public key;
public parent = null;
public children = {};
public docs = new Set();
public end = false;
constructor(key: string) {
this.key = key;
}
}
trieNode.ts
MicheleRivaCode
class TrieNode implements ITrieNode {
public key;
public parent = null;
public children = {};
public docs = new Set();
public end = false;
constructor(key: string) {
this.key = key;
}
getWord(): NodeContent {
let node: TrieNode = this;
let output = "";
while (node !== null) {
output = node.key + output;
node = node.parent!;
}
return [output, this.docs];
}
}
trieNode.ts
MicheleRivaCode
MicheleRivaCode
class TrieNode implements ITrieNode {
public key;
public parent = null;
public children = {};
public docs = new Set();
public end = false;
constructor(key: string) {
this.key = key;
}
getWord() {
let output = "";
let node = this;
while (node !== null) {
output = node.key + output;
node = node.parent!;
}
return [output, this.docs];
}
removeDoc(docID: string): boolean {
return this.docs.delete(docID);
}
}
trieNode.ts
MicheleRivaCode
MicheleRivaCode
TC39 has standardized TCE
(tail-call elimination) with ES6
MicheleRivaCode
MicheleRivaCode
class Trie implements ITrie {
private root = new TrieNode("");
}
trie.ts
MicheleRivaCode
insert(word: string, docId: string): void {
const wordLength = word.length;
let node = this.root;
for (let i = 0; i < wordLength; i++) {
const char = word[i];
if (!node.children?.has(char)) {
const newTrieNode = new TrieNode(char);
newTrieNode.setParent(node);
node.children!.set(char, newTrieNode);
}
node = node.children!.get(char)!;
if (i === wordLength - 1) {
node.setEnd(true);
node.docs.add(docId);
}
}
}
trie.ts
find(prefix: string): FindResult {
let node = this.root;
const output: FindResult = {};
for (const char of prefix) {
if (node?.children?.has(char)) {
node = node.children.get(char)!;
} else {
return output;
}
}
findAllWords(node, output);
function findAllWords(_node: TrieNode, _output: FindResult) {
if (_node.end) {
const [word, docIDs] = _node.getWord();
if (!(word in _output)) {
_output[word] = new Set();
}
if (docIDs?.size) {
for (const doc of docIDs) {
_output[word].add(doc);
}
}
}
for (const childNode of _node.children?.values() ?? []) {
findAllWords(childNode, _output);
}
}
return output;
}
MicheleRivaCode
✅ Tokenizer
✅ Prefix-tree
❌ Typo-tolerance
MicheleRivaCode
trie.find("wrld");
// Resuls:
[
{
id: 1,
quote: "Hello, World!"
},
{
id: 2,
quote: "What a wonderful world"
}
]
MicheleRivaCode
An algorithmic technique for solving an optimization problem by breaking it down into simpler subproblems and utilizing the fact that the optimal solution to the overall problem depends upon the optimal solution to its subproblems.
https://educative.io
MicheleRivaCode
MicheleRivaCode
MicheleRivaCode
The Levenshtein algorithm calculates the least number of edit operations that are necessary to modify one string to obtain another string.
MicheleRivaCode
const word1 = "moon";
const word2 = "lions";
levenshtein(word1, word2); // => 3
MicheleRivaCode
Insert
Delete
Replace
MicheleRivaCode
Edit distance of "Moon" and "Lions"
1)
MOON
LIONS
REPLACE
MicheleRivaCode
Edit distance of "Moon" and "Lions"
1)
MOON
LIONS
REPLACE
2)
LOON
LIONS
REPLACE
MicheleRivaCode
Edit distance of "Moon" and "Lions"
1)
MOON
LIONS
REPLACE
2)
LOON
LIONS
REPLACE
3)
LION
LIONS
INSERT
MicheleRivaCode
Λ | L | I | O | N | S | |
---|---|---|---|---|---|---|
Λ | ||||||
M | ||||||
O | ||||||
O | ||||||
N |
Insert
Delete
Replace
MicheleRivaCode
Λ | L | I | O | N | S | |
---|---|---|---|---|---|---|
Λ | ||||||
M | ||||||
O | ||||||
O | ||||||
N |
Insert
Delete
Replace
MO -> L
1
2
3
4
5
6
2
3
4
1
D(2,2)
MicheleRivaCode
Λ | L | I | O | N | S | |
---|---|---|---|---|---|---|
Λ | ||||||
M | ||||||
O | ||||||
O | ||||||
N |
MOO -> O
Insert
Delete
Replace
1
2
3
4
5
6
2
3
4
1
D(4,3)
MicheleRivaCode
Λ | L | I | O | N | S | |
---|---|---|---|---|---|---|
Λ | 0 | |||||
M | ||||||
O | ||||||
O | ||||||
N |
"" -> ""
Insert
Delete
Replace
MicheleRivaCode
Λ | L | I | O | N | S | |
---|---|---|---|---|---|---|
Λ | 0 | 1 | ||||
M | ||||||
O | ||||||
O | ||||||
N |
"" -> "L"
Insert
Delete
Replace
MicheleRivaCode
Λ | L | I | O | N | S | |
---|---|---|---|---|---|---|
Λ | 0 | 1 | 2 | |||
M | ||||||
O | ||||||
O | ||||||
N |
"" -> "LI"
Insert
Delete
Replace
MicheleRivaCode
Λ | L | I | O | N | S | |
---|---|---|---|---|---|---|
Λ | 0 | 1 | 2 | 3 | ||
M | ||||||
O | ||||||
O | ||||||
N |
"" -> "LIO"
Insert
Delete
Replace
MicheleRivaCode
Λ | L | I | O | N | S | |
---|---|---|---|---|---|---|
Λ | 0 | 1 | 2 | 3 | 4 | |
M | ||||||
O | ||||||
O | ||||||
N |
"" -> "LION"
Insert
Delete
Replace
MicheleRivaCode
Λ | L | I | O | N | S | |
---|---|---|---|---|---|---|
Λ | 0 | 1 | 2 | 3 | 4 | 5 |
M | ||||||
O | ||||||
O | ||||||
N |
"" -> "LIONS"
Insert
Delete
Replace
MicheleRivaCode
Λ | L | I | O | N | S | |
---|---|---|---|---|---|---|
Λ | 0 | 1 | 2 | 3 | 4 | 5 |
M | 1 | |||||
O | ||||||
O | ||||||
N |
"M" -> ""
Insert
Delete
Replace
MicheleRivaCode
Λ | L | I | O | N | S | |
---|---|---|---|---|---|---|
Λ | 0 | 1 | 2 | 3 | 4 | 5 |
M | 1 | |||||
O | 2 | |||||
O | ||||||
N |
"MO" -> ""
Insert
Delete
Replace
MicheleRivaCode
Λ | L | I | O | N | S | |
---|---|---|---|---|---|---|
Λ | 0 | 1 | 2 | 3 | 4 | 5 |
M | 1 | |||||
O | 2 | |||||
O | 3 | |||||
N |
"MOO" -> ""
Insert
Delete
Replace
MicheleRivaCode
Λ | L | I | O | N | S | |
---|---|---|---|---|---|---|
Λ | 0 | 1 | 2 | 3 | 4 | 5 |
M | 1 | |||||
O | 2 | |||||
O | 3 | |||||
N | 4 |
"MOON" -> ""
Insert
Delete
Replace
MicheleRivaCode
Λ | L | I | O | N | S | |
---|---|---|---|---|---|---|
Λ | 0 | 1 | 2 | 3 | 4 | 5 |
M | 1 | |||||
O | 2 | |||||
O | 3 | |||||
N | 4 |
Insert
Delete
Replace
1
2
3
4
5
6
2
3
4
1
D(2,1)
MicheleRivaCode
MicheleRivaCode
Λ | L | I | O | N | S | |
---|---|---|---|---|---|---|
Λ | 0 | 1 | 2 | 3 | 4 | 5 |
M | 1 | |||||
O | 2 | |||||
O | 3 | |||||
N | 4 |
+1
2
Insert
Delete
Replace
1
2
3
4
5
6
2
3
4
1
D(2,1)
MicheleRivaCode
Λ | L | I | O | N | S | |
---|---|---|---|---|---|---|
Λ | 0 | 1 | 2 | 3 | 4 | 5 |
M | 1 | |||||
O | 2 | |||||
O | 3 | |||||
N | 4 |
+1
2
+1
2
Insert
Delete
Replace
1
2
3
4
5
6
2
3
4
1
D(2,1)
MicheleRivaCode
Λ | L | I | O | N | S | |
---|---|---|---|---|---|---|
Λ | 0 | 1 | 2 | 3 | 4 | 5 |
M | 1 | |||||
O | 2 | |||||
O | 3 | |||||
N | 4 |
+1
2
+1
2
1
Insert
Delete
Replace
1
2
3
4
5
6
2
3
4
1
D(2,1)
MicheleRivaCode
Λ | L | I | O | N | S | |
---|---|---|---|---|---|---|
Λ | 0 | 1 | 2 | 3 | 4 | 5 |
M | 1 | 1 | ||||
O | 2 | |||||
O | 3 | |||||
N | 4 |
Insert
Delete
Replace
1
2
3
4
5
6
2
3
4
1
MicheleRivaCode
Λ | L | I | O | N | S | |
---|---|---|---|---|---|---|
Λ | 0 | 1 | 2 | 3 | 4 | 5 |
M | 1 | 1 | ||||
O | 2 | |||||
O | 3 | |||||
N | 4 |
+1
2
+1
2
2
Insert
Delete
Replace
1
2
3
4
5
6
2
3
4
1
D(3,1)
MicheleRivaCode
Λ | L | I | O | N | S | |
---|---|---|---|---|---|---|
Λ | 0 | 1 | 2 | 3 | 4 | 5 |
M | 1 | 1 | 2 | 3 | 4 | 5 |
O | 2 | |||||
O | 3 | |||||
N | 4 |
Insert
Delete
Replace
1
2
3
4
5
6
2
3
4
1
MicheleRivaCode
Λ | L | I | O | N | S | |
---|---|---|---|---|---|---|
Λ | 0 | 1 | 2 | 3 | 4 | 5 |
M | 1 | 1 | 2 | 3 | 4 | 5 |
O | 2 | 2 | 2 | |||
O | 3 | |||||
N | 4 |
Insert
Delete
Replace
1
2
3
4
5
6
2
3
4
1
D(4,2)
MicheleRivaCode
MicheleRivaCode
Λ | L | I | O | N | S | |
---|---|---|---|---|---|---|
Λ | 0 | 1 | 2 | 3 | 4 | 5 |
M | 1 | 1 | 2 | 3 | 4 | 5 |
O | 2 | 2 | 2 | |||
O | 3 | |||||
N | 4 |
2
2
Insert
Delete
Replace
1
2
3
4
5
6
2
3
4
1
D(4,2) = D(3,1)
MicheleRivaCode
Λ | L | I | O | N | S | |
---|---|---|---|---|---|---|
Λ | 0 | 1 | 2 | 3 | 4 | 5 |
M | 1 | 1 | 2 | 3 | 4 | 5 |
O | 2 | 2 | 2 | 2 | 3 | 4 |
O | 3 | 3 | 3 | 2 | 3 | 4 |
N | 4 | 4 | 4 | 3 | 2 | 3 |
Insert
Delete
Replace
1
2
3
4
5
6
2
3
4
1
MicheleRivaCode
Λ | L | I | O | N | S | |
---|---|---|---|---|---|---|
Λ | 0 | 1 | 2 | 3 | 4 | 5 |
M | 1 | 1 | 2 | 3 | 4 | 5 |
O | 2 | 2 | 2 | 2 | 3 | 4 |
O | 3 | 3 | 3 | 2 | 3 | 4 |
N | 4 | 4 | 4 | 3 | 2 |
3
Insert
Delete
Replace
1
2
3
4
5
6
2
3
4
1
MicheleRivaCode
Λ | L | I | O | N | S | |
---|---|---|---|---|---|---|
Λ | 0 | 1 | 2 | 3 | 4 | 5 |
M | 1 | 1 | 2 | 3 | 4 | 5 |
O | 2 | 2 | 2 | 2 | 3 | 4 |
O | 3 | 3 | 3 | 2 | 3 | 4 |
N | 4 | 4 | 4 | 3 | 2 |
0
Insert
Delete
Replace
1
2
2
2
3
1
2
3
4
5
6
2
3
4
1
MicheleRivaCode
Edit distance of "Moon" and "Lions"
1)
MOON
LIONS
REPLACE
2)
LOON
LIONS
REPLACE
3)
LION
LIONS
INSERT
MicheleRivaCode
Λ | P | O | S | E | R | |
---|---|---|---|---|---|---|
Λ | 0 | 1 | 2 | 3 | 4 | 5 |
H | 1 | 1 | 2 | 3 | 4 | 5 |
O | 2 | 2 | 1 | 2 | 3 | 4 |
R | 3 | 3 | 2 | 2 | 3 | 3 |
S | 4 | 4 | 3 | 2 | 3 | 4 |
E | 5 | 5 | 4 | 3 | 2 |
Levenshtein distance of Horse - Poser
3
MicheleRivaCode
Levenshtein distance of Race - Raise
Λ | R | A | I | S | E | |
---|---|---|---|---|---|---|
Λ | 0 | 1 | 2 | 3 | 4 | 5 |
R | 1 | 0 | 1 | 2 | 3 | 4 |
I | 2 | 1 | 0 | 1 | 2 | 3 |
C | 3 | 2 | 1 | 1 | 2 | 3 |
E | 4 | 3 | 2 | 2 | 2 |
2
MicheleRivaCode
export function levenshtein(a: string, b: string): number {
if (!a.length) return b.length;
if (!b.length) return a.length;
let tmp;
if (a.length > b.length) {
tmp = a;
a = b;
b = tmp;
}
const row = Array.from({ length: a.length + 1 }, (_, i) => i);
let val = 0;
for (let i = 1; i <= b.length; i++) {
let prev = i;
for (let j = 1; j <= a.length; j++) {
if (b[i - 1] === a[j - 1]) {
val = row[j - 1];
} else {
val = Math.min(row[j - 1] + 1, Math.min(prev + 1, row[j] + 1));
}
row[j - 1] = prev;
prev = val;
}
row[a.length] = prev;
}
return row[a.length];
}
MicheleRivaCode
Simple fast algorithms for the editing distance between trees and related problems
Kaizhong Zhang and Dennis Shasha
https://shorturl.at/otBMY
MicheleRivaCode
MicheleRivaCode
import { Lyra } from '@nearform/lyra';
const db = new Lyra({
schema: {
author: 'string',
quote: 'string'
}
});
MicheleRivaCode
await db.insert({
quote: 'It is during our darkest moments that we must focus to see the light.',
author: 'Aristotle'
});
await db.insert({
quote: 'If you really look closely, most overnight successes took a long time.',
author: 'Steve Jobs'
});
await db.insert({
quote: 'If you are not willing to risk the usual, you will have to settle for the ordinary.',
author: 'Jim Rohn'
});
await db.insert({
quote: 'You miss 100% of the shots you don\'t take',
author: 'Wayne Gretzky - Michael Scott'
});
MicheleRivaCode
const searchResult = await db.search({
term: 'if',
properties: ['quote']
});
// Result
{
elapsed: '99μs',
hits: [
{
id: 'ckAOPGTA5qLXx0MgNr1Zy',
quote: 'If you really look closely, most overnight successes took a long time.',
author: 'Steve Jobs'
},
{
id: 'fyl-_1veP78IO-wszP86Z',
quote: 'If you are not willing to risk the usual, you will have to settle for the ordinary.',
author: 'Jim Rohn'
}
],
count: 2
}
MicheleRivaCode
const searchResult = await db.search({
term: 'Michael',
properties: '*'
});
// Result
{
elapsed: '111μs',
hits: [
{
id: 'L1tpqQxc0c2djrSN2a6TJ',
quote: "You miss 100% of the shots you don't take",
author: 'Wayne Gretzky - Michael Scott'
}
],
count: 1
}
MicheleRivaCode
MicheleRivaCode
npm i @nearform/lyra
MicheleRivaCode
MicheleRivaCode
Build scalable, high performances and modern web applications using Next.js, the React framework for production
MicheleRivaCode
MicheleRivaCode
@MicheleRiva
@MicheleRivaCode
/in/MicheleRiva95
www.micheleriva.dev