提交 63ca8c23 编写于 作者: C Cyrus Najmabadi

Move to a builder pattern for creating a BKTree.

上级 fc65b4b2
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Roslyn.Utilities
{
internal partial class BKTree
{
private class Builder
{
private readonly char[][] values;
public Builder(IEnumerable<string> values)
{
this.values = values.Select(v => v.ToLower()).Distinct().Select(v => v.ToCharArray()).ToArray();
}
internal BKTree Create()
{
var nodes = new List<Node>();
foreach (var value in values)
{
if (value.Length > 0)
{
Add(nodes, value);
}
}
return new BKTree(nodes.ToArray());
}
private static void Add(List<Node> nodes, char[] lowerCaseCharacters)
{
if (nodes.Count == 0)
{
nodes.Add(new Node(lowerCaseCharacters));
return;
}
var currentNodeIndex = 0;
while (true)
{
var currentNode = nodes[currentNodeIndex];
var editDistance = EditDistance.GetEditDistance(currentNode.LowerCaseCharacters, lowerCaseCharacters);
// This shoudl never happen. We dedupe all items before proceeding to the 'Add' step.
Debug.Assert(editDistance != 0);
if (currentNode.AllChildren == null)
{
currentNode.AllChildren = new Dictionary<int, int>();
nodes[currentNodeIndex] = currentNode;
// Fall through. to actually add the child to this node.
}
else
{
int childNodeIndex;
if (currentNode.AllChildren.TryGetValue(editDistance, out childNodeIndex))
{
// Edit distances collide. Move to this child and add this word to it.
currentNodeIndex = childNodeIndex;
continue;
}
// Fall through. to actually add the child to this node.
}
currentNode.AllChildren.Add(editDistance, nodes.Count);
nodes.Add(new Node(lowerCaseCharacters));
return;
}
}
}
}
}
......@@ -10,7 +10,7 @@
namespace Roslyn.Utilities
{
internal class BKTree
internal partial class BKTree
{
// Root node is at index 0.
private readonly Node[] nodes;
......@@ -48,67 +48,7 @@ public static BKTree Create(params string[] values)
public static BKTree Create(IEnumerable<string> values)
{
return Create(values.Select(v => v.ToLower()).Distinct().Select(v => v.ToCharArray()).ToArray());
}
private static BKTree Create(char[][] values)
{
var nodes = new List<Node>();
foreach (var value in values)
{
if (value.Length > 0)
{
Add(nodes, value);
}
}
return new BKTree(nodes.ToArray());
}
private static void Add(List<Node> nodes, char[] lowerCaseCharacters)
{
if (nodes.Count == 0)
{
nodes.Add(new Node(lowerCaseCharacters));
return;
}
var currentNodeIndex = 0;
while (true)
{
var currentNode = nodes[currentNodeIndex];
var editDistance = EditDistance.GetEditDistance(currentNode.LowerCaseCharacters, lowerCaseCharacters);
if (editDistance == 0)
{
// Already in the graph. Can happen because we added something that is the same
// as an existing item, but only differs in case.
return;
}
if (currentNode.AllChildren == null)
{
currentNode.AllChildren = new Dictionary<int, int>();
nodes[currentNodeIndex] = currentNode;
// Fall through. to actually add the child to this node.
}
else
{
int childNodeIndex;
if (currentNode.AllChildren.TryGetValue(editDistance, out childNodeIndex))
{
// Edit distances collide. Move to this child and add this word to it.
currentNodeIndex = childNodeIndex;
continue;
}
// Fall through. to actually add the child to this node.
}
currentNode.AllChildren.Add(editDistance, nodes.Count);
nodes.Add(new Node(lowerCaseCharacters));
return;
}
return new Builder(values).Create();
}
public IList<string> Find(string value, int? threshold = null)
......
......@@ -949,6 +949,7 @@
<SubType>
</SubType>
</None>
<Compile Include="Utilities\BKTree.Builder.cs" />
<PublicAPI Include="PublicAPI.Shipped.txt" />
<PublicAPI Include="PublicAPI.Unshipped.txt" />
</ItemGroup>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册