how to return the result outside the if statement - c#-4.0

I was writing a revit pluging using c#. I couldn't return the result without assign public variable. Below is my code.I am not sure what is the error. Error in last codeline - return stid
public ElementId sysid(Duct elt, Document doc)
{
ElementId stid;
FilteredElementCollector DuctSystemcollector = new FilteredElementCollector(doc);
ICollection<Element> DuctSystem = DuctSystemcollector.OfClass(typeof(MechanicalSystemType)).ToElements();
foreach (Element j in DuctSystem)
{
string sn = j.GetParameters("Type Name")[0].AsString();
if (sn == elt.GetParameters("System Type")[0].AsValueString())
{
stid = j.Id;
//return stid;
//TaskDialog.Show("Duct shape ", stid);
}
}
return stid;
}

Related

Changing the Default Option for Column Filters

Is it possible to change the default option all column filters? I'm pretty sure I can accomplish this with some JavaScript, but I'd like to know if there's any way within the Acumatica framework to change this.
The answer will be no. The filter is inside the PX.Web.UI.dll in the PXGridFilter class which is an internal class. The property that you are interested in is the Condition.
The value is set inside one of the private methods of the PXGrid class. The code of the method is below:
private IEnumerable<PXGridFilter> ab()
{
List<PXGridFilter> list = new List<PXGridFilter>();
if (this.FilterID != null)
{
Guid? filterID = this.FilterID;
Guid guid = PXGrid.k;
if (filterID == null || (filterID != null && filterID.GetValueOrDefault() != guid))
{
using (IEnumerator<PXResult<FilterRow>> enumerator = PXSelectBase<FilterRow, PXSelect<FilterRow, Where<FilterRow.filterID, Equal<Required<FilterRow.filterID>>, And<FilterRow.isUsed, Equal<True>>>>.Config>.Select(this.DataGraph, new object[]
{
this.FilterID.Value
}).GetEnumerator())
{
while (enumerator.MoveNext())
{
FilterRow row = enumerator.Current;
string dataField = row.DataField;
PXCache pxcache = PXFilterDetailView.TargetCache(this.DataGraph, new Guid?(this.FilterID.Value), ref dataField);
if (this.Columns[row.DataField] != null)
{
List<PXGridFilter> list2 = list;
int valueOrDefault = row.OpenBrackets.GetValueOrDefault();
string dataField2 = row.DataField;
string dataField3 = row.DataField;
int value = (int)row.Condition.Value;
object value2 = pxcache.ValueFromString(dataField, row.ValueSt);
string valueText = row.ValueSt.With((string _) => this.Columns[row.DataField].FormatValue(_));
object value3 = pxcache.ValueFromString(dataField, row.ValueSt2);
string value2Text = row.ValueSt2.With((string _) => this.Columns[row.DataField].FormatValue(_));
int valueOrDefault2 = row.CloseBrackets.GetValueOrDefault();
int? #operator = row.Operator;
int num = 1;
list2.Add(new PXGridFilter(valueOrDefault, dataField2, dataField3, value, value2, valueText, value3, value2Text, valueOrDefault2, #operator.GetValueOrDefault() == num & #operator != null));
}
}
return list;
}
}
}
if (this.FilterRows != null && this.FilterRows.Count > 0)
{
for (int i = 0; i < this.FilterRows.Count; i++)
{
PXFilterRow row = this.FilterRows[i];
list.Add(new PXGridFilter(row.OpenBrackets, row.DataField, row.DataField, (int)row.Condition, row.Value, row.Value.With(delegate(object _)
{
if (this.Columns[row.DataField] == null)
{
return _.ToString();
}
return this.Columns[row.DataField].FormatValue(_);
}), row.Value2, row.Value2.With(delegate(object _)
{
if (this.Columns[row.DataField] == null)
{
return _.ToString();
}
return this.Columns[row.DataField].FormatValue(_);
}), row.CloseBrackets, row.OrOperator));
}
}
return list;
}
UPDATE
The below JS code allows you to change the condition of the last set filter:
px_all.ctl00_phG_grid_fd.show();
px_all.ctl00_phG_grid_fd_cond.items.items[7].setChecked(true);
px_all.ctl00_phG_grid_fd_ok.element.click();
px_all.ctl00_phG_grid_fd_cond.items.items[7].value "EQ"
px_all.ctl00_phG_grid_fd_cond.items.items[8].value "NE"
px_all.ctl00_phG_grid_fd_cond.items.items[9].value "GT"
px_all.ctl00_phG_grid_fd_cond.items.items[13].value "LIKE"
px_all.ctl00_phG_grid_fd_cond.items.items[14].value "LLIKE"
px_all.ctl00_phG_grid_fd_cond.items.items[15].value "RLIKE"
px_all.ctl00_phG_grid_fd_cond.items.items[16].value "NOTLIKE"
px_all.ctl00_phG_grid_fd_cond.items.items[18].value "ISNULL"
px_all.ctl00_phG_grid_fd_cond.items.items[19].value "ISNOTNULL"

Windows Form in a Revit Addin

I have written quite a few different add-ins now but I keep struggling to get a windows form working on Revit. The program builds fine and I have the dll set up for Revit to access.
Here are the different sections of my code. The program is more extensive than what is seen but I believe that the problem is a reference issue or a problem with my ADDIN file. Maybe there is a different way I need to set up my ADDIN file since I have a windows form in it?? Let me know.
Here is a Dropbox folder with the screenshots in it.
Let me know if there is anything else you need to see. The error in Revit says it has to do with the FullName but I believe I put it in the ADDIN file correctly, and I did it the same as I had for other ADDINs.
Thank you for your help!
[TransactionAttribute(TransactionMode.Manual)]
[RegenerationAttribute(RegenerationOption.Manual)]
public class CicuitChecker : IExternalCommand
{
public Result Execute(
ExternalCommandData commandData,
ref string message,
ElementSet elements)
{
//set document variable
Document document = commandData.Application.ActiveUIDocument.Document;
using (Transaction trans = new Transaction(document))
{
trans.Start("Circuit Checker");
UIApplication uiApp = commandData.Application;
Document doc = uiApp.ActiveUIDocument.Document;
//run through looped form in case of user not selecting needed fields, and store what family the user wants the program to check
Boolean messedUp = false;
Boolean All = false, lightF = false, recep = false, elecEquip = false, equipCon = false, junc = false, panels = false;
FilteredElementCollector collector = new FilteredElementCollector(doc), collector2 = new FilteredElementCollector(doc);
while (messedUp)
{
CircuitChecker.CircuitCheckerForm form = new CircuitChecker.CircuitCheckerForm();
form.ShowDialog();
//Get application and document objects
foreach (String item in form.getSelectionElementsLB())
{
if (item.Equals("All"))
{
All = true;
break;
}
else if (item.Equals("Lighting Fixtures"))
{
lightF = true;
}
else if (item.Equals("Recepticales"))
{
recep = true;
}
else if (item.Equals("Electrical Equipment (including Panels)"))
{
elecEquip = true;
}
else if (item.Equals("Junctions"))
{
junc = true;
}
else
{
messedUp = true;
TaskDialog.Show("Error", "At least one element must be selected.");
}
}
if (form.getSelectionPlaceLB().Equals("Entire Project"))
{
collector
= new FilteredElementCollector(doc)
.WhereElementIsNotElementType();
collector2
= new FilteredElementCollector(doc)
.WhereElementIsNotElementType();
}
else if (form.getSelectionPlaceLB().Equals("Elements in Current View"))
{
collector
= new FilteredElementCollector(doc, document.ActiveView.Id)
.WhereElementIsNotElementType();
collector2
= new FilteredElementCollector(doc, document.ActiveView.Id)
.WhereElementIsNotElementType();
}
else
{
messedUp = true;
TaskDialog.Show("Error", "A place must be selected.");
}
}
Color color = new Color(138, 43, 226); // RGB
OverrideGraphicSettings ogs = new OverrideGraphicSettings();
OverrideGraphicSettings ogsOriginal = new OverrideGraphicSettings();
ogs.SetProjectionLineColor(color);
int notCircuited = 0;
//ElementId symbolId = family
ElementCategoryFilter lightFilter = new ElementCategoryFilter(BuiltInCategory.OST_LightingFixtures);
ElementCategoryFilter recepFilter = new ElementCategoryFilter(BuiltInCategory.OST_ElectricalFixtures);
ElementCategoryFilter elecEquipFilter = new ElementCategoryFilter(BuiltInCategory.OST_ElectricalEquipment);
//ElementClassFilter filter = new ElementClassFilter(typeof("Junction Boxes - Load"));
//FamilyInstanceFilter juncFilter1 = new FamilyInstanceFilter(doc, );
LogicalOrFilter first = new LogicalOrFilter(lightFilter, recepFilter);
if (All)
{
collector.WherePasses(first);
IList<Element> allArr = collector.ToElements();
foreach (Element e in allArr)
{
int cirNum = e.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_NUMBER).AsInteger();
String panel = e.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_PANEL_PARAM).AsString();
if (!(IsNumeric(cirNum)) || (panel.Equals("")) || (panel.Equals("<unnamed>")))
{
doc.ActiveView.SetElementOverrides(e.Id, ogs);
notCircuited++;
}
else
{
doc.ActiveView.SetElementOverrides(e.Id, ogsOriginal);
}
}
collector2.WherePasses(elecEquipFilter);
IList<Element> elecEquipArr = collector.ToElements();
foreach (Element e in elecEquipArr)
{
String panel = e.get_Parameter(BuiltInParameter.RBS_ELEC_PANEL_SUPPLY_FROM_PARAM).AsString();
if ((panel.Equals("")))
{
doc.ActiveView.SetElementOverrides(e.Id, ogs);
notCircuited++;
}
else
{
doc.ActiveView.SetElementOverrides(e.Id, ogsOriginal);
}
}
TaskDialog.Show("Circuit Checker", notCircuited + " lighting fixtures are not circuited in this view.");
trans.Commit();
}
if (!trans.HasEnded())
{
if (lightF)
{
collector.WherePasses(lightFilter);
IList<Element> lightArr = collector.ToElements();
foreach (Element e in lightArr)
{
int cirNum = e.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_NUMBER).AsInteger();
String panel = e.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_PANEL_PARAM).AsString();
if (!(IsNumeric(cirNum)) || (panel.Equals("")) || (panel.Equals("<unnamed>")))
{
doc.ActiveView.SetElementOverrides(e.Id, ogs);
notCircuited++;
}
else
{
doc.ActiveView.SetElementOverrides(e.Id, ogsOriginal);
}
}
}
if (recep)
{
collector.WherePasses(recepFilter);
IList<Element> recepArr = collector.ToElements();
foreach (Element e in recepArr)
{
int cirNum = e.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_NUMBER).AsInteger();
String panel = e.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_PANEL_PARAM).AsString();
if (!(IsNumeric(cirNum)) || (panel.Equals("")) || (panel.Equals("<unnamed>")))
{
doc.ActiveView.SetElementOverrides(e.Id, ogs);
notCircuited++;
}
else
{
doc.ActiveView.SetElementOverrides(e.Id, ogsOriginal);
}
}
}
if (elecEquip)
{
collector.WherePasses(elecEquipFilter);
IList<Element> elecEquipArr = collector.ToElements();
foreach (Element e in elecEquipArr)
{
String panel = e.get_Parameter(BuiltInParameter.RBS_ELEC_PANEL_SUPPLY_FROM_PARAM).AsString();
if ((panel.Equals("")))
{
doc.ActiveView.SetElementOverrides(e.Id, ogs);
notCircuited++;
}
else
{
doc.ActiveView.SetElementOverrides(e.Id, ogsOriginal);
}
}
}
if (junc)
{
collector.WherePasses(recepFilter);
IList<Element> juncArr = collector.ToElements();
foreach (Element e in juncArr)
{
int cirNum = e.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_NUMBER).AsInteger();
String panel = e.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_PANEL_PARAM).AsString();
if (!(IsNumeric(cirNum)) || (panel.Equals("")) || (panel.Equals("<unnamed>")))
{
doc.ActiveView.SetElementOverrides(e.Id, ogs);
notCircuited++;
}
else
{
doc.ActiveView.SetElementOverrides(e.Id, ogsOriginal);
}
}
}
TaskDialog.Show("Circuit Checker", notCircuited + " lighting fixtures are not circuited in this view.");
trans.Commit();
}
}
return Result.Succeeded;
}
public static Boolean IsNumeric(Object Expression)
{
if (Expression == null || Expression is DateTime)
return false;
if (Expression is Int16 || Expression is Int32 || Expression is Int64 || Expression is Decimal || Expression is Single || Expression is Double || Expression is Boolean)
return true;
try
{
if (Expression is string)
Double.Parse(Expression as string);
else
Double.Parse(Expression.ToString());
return true;
}
catch { } // just dismiss errors but return false
return false;
}
}
This code is having the functionality in the 'main class.' I have since moved the functionality to the form class as konrad suggested but am still receiving the FullClassName error in Revit. Please Help!
The schedule data add-in provides a full Visual Studio solution demonstrating how to display a Windows form in a Revit add-in, including the generation of the Windows form on the fly:
http://thebuildingcoder.typepad.com/blog/2012/05/the-schedule-api-and-access-to-schedule-data.html
Here's how I usually set up my Windows Forms based External Commands. Remember that you have to create an External Command, and your addin manifest must point at this class. Then from this class you can launch the Form like so:
[Transaction(TransactionMode.Manual)]
public class SomeCommand : IExternalCommand
{
public Result Execute(
ExternalCommandData commandData,
ref string message,
ElementSet elements)
{
// Get application and document objects
UIApplication uiApp = commandData.Application;
Document doc = uiApp.ActiveUIDocument.Document;
UIDocument uidoc = uiApp.ActiveUIDocument;
try
{
SomeNamespace.SomeForm form = new SomeNamespace.SomeForm(doc);
form.ShowDialog();
return Result.Succeeded;
}
// Catch any exceptions and display them
catch (Autodesk.Revit.Exceptions.OperationCanceledException)
{
return Result.Cancelled;
}
catch (Exception ex)
{
message = ex.Message;
return Result.Failed;
}
}
}
So I have a Form class that I instantiate from my ExternalCommand and pass Document to its constructor. That way I have access to document when I am interacting with the form later. I wire up all functionality in code behind of the Form.
Agree, the OP's question is why doesn't the addin work...
From looking at the images, it seems like the issue is that Revit is not properly finding the full class name of the command.
It's a little unusual that you don't have your command class wrapped in a namespace (your form class is, for example).
I would recommend wrapping it in a namespace like "circuitchecker" - like your form class.
Then the "full name" in the addin file would become "circuitchecker.circuitchecker"
(the namespace.classname) - this helps Revit distinguish different classes that might have the same name.
side note: I don't believe that putting a URL into the Image/LargeImage fields in the addin will work - but not positive.

C# FileCreationTime

I have the below module which is part of a larger program for searching the text within DOCX files. This is the code for when the search button is clicked;
{
this.resultListView.Items.Clear();
try
{
foreach (var filePath in Search(this.txtDirectory.Text, this.txtSearch.Text, this.cBoxUseSubdirectories.Checked, this.cBoxCaseSensitive.Checked, this.rBtnRegex.Checked))
{
var file = new FileInfo(filePath);
this.resultListView.Items.Add(new ListViewItem(new string[] { file.Name, string.Format("{0:0.0}", file.Length / 1024d), file.FullName}));
}
}
catch (Exception ex)
{
MessageBox.Show(this, string.Format("Exception details:\n{0}", ex), string.Format("Exception '{0}' occurred.", ex.GetType()), MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
This is the code for the Search method which is called with the arguments above;
private static IEnumerable<string> Search(string directory, string searchString, bool searchSubdirectories, bool caseSensitive, bool useRegex)
{
var isMatch = useRegex ? new Predicate<string>(x => Regex.IsMatch(x, searchString, caseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase))
: new Predicate<string>(x => x.IndexOf(searchString, caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase) >= 0);
foreach (var filePath in Directory.GetFiles(directory, "*.docx", searchSubdirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly))
{
string docxText;
using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
docxText = new DocxToStringConverter(stream).Convert();
if (isMatch(docxText))
yield return filePath;
}
}
There are other classes which I do not think are relevant here.
the results are populated in a listview via this;
this.resultListView.Items.Add(new ListViewItem(new string[] { file.Name, string.Format("{0:0.0}", file.Length / 1024d), file.FullName}));
}
I want to add an extra column to show the file creation date for the found files. I tried adding this;
var fileCreatedDate = File.GetCreationTime(filePath);
then adding file.fileCreatedDate to the this.resultListView.Items.Add but it didn't work.
Any suggestions on how to pull the file created date out of the existing code?
Return an IEnumerable of Tuple instances.
private static IEnumerable<Tuple<string, DateTime>> Search(string directory, string searchString, bool searchSubdirectories, bool caseSensitive, bool useRegex)
{
var isMatch = useRegex ? new Predicate<string>(x => Regex.IsMatch(x, searchString, caseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase))
: new Predicate<string>(x => x.IndexOf(searchString, caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase) >= 0);
foreach (var filePath in Directory.GetFiles(directory, "*.docx", searchSubdirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly))
{
string docxText;
using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
docxText = new DocxToStringConverter(stream).Convert();
if (isMatch(docxText))
yield return new Tuple<string, DateTime>(filePath, System.IO.File.GetLastWriteTime(filePath));
}
}
Tuple will have two properties: Item1, and Item2. Item1 is the path, and Item2 is the date.
You could also use your own class in place of the Tuple, but the Tuple was simple to code.
Through some trial and error I managed to sort the problem.
I added this to the initial button click code;
var fileCreatedDate = File.GetCreationTime(filePath);
and then this;
this.resultListView.Items.Add(new ListViewItem(new string[] { file.Name, string.Format("{0:0.0}", file.Length / 1024d), file.FullName, fileCreatedDate.ToString()}));
the fileCreated.ToString() sorts it.

Getting a random UserProfile In SharePoint 2010

I am trying to retrieve a random number of users from the UserProfileManager.
But I am encountering errors when deploying to the live servers. I can't seem to see what is causing the error. My code is below:
for (int i = 0; i < NumberOfUserLimit; i++)
{
UserProfile up = profileManager.GetUserProfile(random.Next(1, NumberOfUserLimit));
if (up["FirstName"] != null && up["FirstName"].Value != null && !String.IsNullOrEmpty(up["FirstName"].Value.ToString()))
{
DataRow drUserProfile;
drUserProfile = dtUserProfile.NewRow();
drUserProfile["DisplayName"] = up.DisplayName;
drUserProfile["FirstName"] = up["FirstName"].Value;
drUserProfile["LastName"] = up["LastName"].Value;
drUserProfile["Department"] = up["Department"].Value;
drUserProfile["Location"] = up["SPS-Location"].Value;
drUserProfile["HireDate"] = up["SPS-HireDate"].Value;
drUserProfile["ContactNumber"] = up["Office"].Value;
if (up["PictureURL"] != null && up["PictureURL"].Value != null && !String.IsNullOrEmpty(up["PictureURL"].Value.ToString()))
{
string cleanAccountName = up["AccountName"].Value.ToString().Replace(#"\", "_");
string pictureUrl = String.Format("https://my.someintranet.com/User Photos/Profile Pictures/{0}_MThumb.jpg", cleanAccountName);
drUserProfile["Image"] = pictureUrl;
}
else
{
drUserProfile["Image"] = "~/_layouts/images/O14_person_placeHolder_96.png";
}
drUserProfile["MySiteUrl"] = up.PublicUrl;
dtUserProfile.Rows.Add(drUserProfile);
}
}
My code works when I apply a simple foreach to my code above instead of the "for loop":
foreach (UserProfile up in profileManager)
Which proves I can return userprofiles.
Any help is appreciated.
profileManager.GetUserProfile(long recordId)
expects a recordId from userprofile table. It is not an index, so you cannot use "random".
If you want to check RecordId, you can take a look at SQL tables of ProfileDB. Table "UserProfile_Full" has MasterRecordId column. Your parameter in GetUserProfile has to match of the user profile's MasterRecordId.
you can use the following code to get your random profiles:
IEnumerator profiles = profileManager.GetEnumerator();
int index = new Random().Next(1, 100);
while (index >= 0 && profiles.MoveNext())
index--;
UserProfile currentProfile = (UserProfile)profiles.Current
Code that handles Random better
public class TestClass
{
private random = new Random();
private long totalNumberOfProfiles; //ProfileManager.Count not always returns count correctly
public TestClass()
{
//this does not have to be in constructor but point is to have it cached (reasonably)
IEnumerator profiles = profileManager.GetEnumerator();
long counter = 0;
while (profiles.MoveNext())
counter++;
this.totalNumberOfProfiles = counter;
}
public fillInDataSet()
{
//something is here...
IEnumerator profiles = profileManager.GetEnumerator();
int index = random.Next(1, totalNumberOfProfiles);
while (index >= 0 && profiles.MoveNext())
index--;
UserProfile currentProfile = (UserProfile)profiles.Current
//something is here...
}
}

Easy way to search a string for strings

I'm trying to find the easiest way to search a string for an array of possible strings. I know the easy way to do this for characters is to use myString.IndexOfAny(charArray). But how what if I'd like to search my string for strings and not just characters? Are there any .net tricks or methods that make this easier?
Basically, I'd like to do something like this:
string myName = "rahkim";
string[] names = new string[] {"joe","bob","chris"};
if(myName.IndexOfAny(names) >= 0)
{
//success code//
}
I know there are ways to do this with loops, etc. But I was hoping for something inherent in the framework.
You should define if you want to to find equal strings or search for a matching substring. Both ways are easy pre-LINQ and with LINQ.
string myName = "rahkim";
string[] names = new string[] { "joe", "bob", "chris" };
Equal Strings, LINQ
bool contains = names.Contains(myName);
Equal Strings, Pre-LINQ
bool contains = new List<string>(name).Contains(myName);
Substrings, LINQ
bool contains = names.Any(name => name.Contains(myName));
Substring, Pre-LINQ
bool contains = false;
foreach(string name in names)
if (name.Contains(myName))
contains = true;
If anyone else found this while trying to search for a .Net method like String.IndexOfAny(String[]), this is my solution:
C#
public int IndexOfAny(string test, string[] values)
{
int first = -1;
foreach (string item in values) {
int i = test.IndexOf(item);
if (i >= 0) {
if (first > 0) {
if (i < first) {
first = i;
}
} else {
first = i;
}
}
}
return first;
}
VB
Public Function IndexOfAny(test As String, values As String()) As Integer
Dim first As Integer = -1
For Each item As String In values
Dim i As Integer = test.IndexOf(item)
If i >= 0 Then
If first > 0 Then
If i < first Then
first = i
End If
Else
first = i
End If
End If
Next
Return first
End Function
You can do a LastIndexOfAny(String[]) by just switching the
i < first
to
i > first
You can (also) use the static IndexOf method of the Array class:
bool hasName = Array.IndexOf(names, myName) > -1;
int IndexOfAny(String[] rgs) would indeed be nice but it's nominally an O(n^2) operation. If, in your application, the set of strings rgs is large and always the same, the most efficient approach is to load them into a trie data structure once, and then use the trie repeatedly to search for them within the unknown strings given at runtime.
Here is the relevant code, adapted from a C# trie source I found on the web, attributed to "Kerry D. Wong." In my version, each string in the trie has a "payload" of generic type TValue. To use this trie to simply search for substrings, the payload could always be set to true, as illustrated with simple_trie.
The other thing I changed here is that this trie automatically adapts allow for storage of arbitrary Unicode strings. The array at each node—which characterizes a trie—adjusts its base and length to accomodate the range of Unicode characters which need to be stored at that node. This allows for case-sensitive matching, for example.
The C# 3.0 initialization syntax is handy for this trie, but enabling it requires a dummy implementation of IEnumerable in order to compile. The CLR doesn't seem to call GetEnumerator() and I suggest that you don't try to enumerate with its result either.
using System;
using System.Collections.Generic;
using System.Linq; // only used in Main()
class Program
{
// trie with payload of type <String>
static Trie<String> value_trie = new Trie<String>
{
{ "rabbit", "cute" },
{ "giraffe", "tall" },
{ "ape", "smart" },
{ "hippo", "large" },
};
// degenerate case of a trie without payload
static Trie<bool> simple_trie = new Trie<bool>
{
{ "rabbit", true },
{ "giraffe", true },
{ "ape", true },
{ "hippo", true },
};
static void Main(String[] args)
{
String s = "Once upon a time, a rabbit met an ape in the woods.";
// Retrieve payloads for words in the string.
//
// output:
// cute
// smart
foreach (String word in value_trie.AllSubstringValues(s))
Console.WriteLine(word);
// Simply test a string for any of the words in the trie.
// Note that the Any() operator ensures that the input is no longer
// traversed once a single result is found.
//
// output:
// True
Console.WriteLine(simple_trie.AllSubstringValues(s).Any(e=>e));
s = "Four score and seven years ago.";
// output:
// False
Console.WriteLine(simple_trie.AllSubstringValues(s).Any(e => e));
}
}
class TrieNode<TValue>
{
private TrieNode<TValue>[] nodes = null;
private TValue m_value = default(TValue);
private Char m_base;
public Char Base { get { return m_base; } }
public bool IsEnd { get { return !m_value.Equals(default(TValue)); } }
public TValue Value
{
get { return m_value; }
set { m_value = value; }
}
public IEnumerable<TrieNode<TValue>> Nodes { get { return nodes; } }
public TrieNode<TValue> this[char c]
{
get
{
if (nodes != null && m_base <= c && c < m_base + nodes.Length)
return nodes[c - m_base];
return null;
}
}
public TrieNode<TValue> AddChild(char c)
{
if (nodes == null)
{
m_base = c;
nodes = new TrieNode<TValue>[1];
}
else if (c >= m_base + nodes.Length)
{
Array.Resize(ref nodes, c - m_base + 1);
}
else if (c < m_base)
{
Char c_new = (Char)(m_base - c);
TrieNode<TValue>[] tmp = new TrieNode<TValue>[nodes.Length + c_new];
nodes.CopyTo(tmp, c_new);
m_base = c;
nodes = tmp;
}
TrieNode<TValue> node = nodes[c - m_base];
if (node == null)
{
node = new TrieNode<TValue>();
nodes[c - m_base] = node;
}
return node;
}
};
class Trie<TValue> : System.Collections.IEnumerable
{
private TrieNode<TValue> _root = new TrieNode<TValue>();
// This dummy enables C# 3.0 initialization syntax
public System.Collections.IEnumerator GetEnumerator()
{
return null;
}
public void Add(String s, TValue v)
{
TrieNode<TValue> node = _root;
foreach (Char c in s)
node = node.AddChild(c);
node.Value = v;
}
public bool Contains(String s)
{
TrieNode<TValue> node = _root;
foreach (Char c in s)
{
node = node[c];
if (node == null)
return false;
}
return node.IsEnd;
}
public TValue Find(String s_in)
{
TrieNode<TValue> node = _root;
foreach (Char c in s_in)
{
node = node[c];
if (node == null)
return default(TValue);
}
return node.Value;
}
public IEnumerable<TValue> FindAll(String s_in)
{
TrieNode<TValue> node = _root;
foreach (Char c in s_in)
{
node = node[c];
if (node == null)
break;
if (node.Value != null)
yield return node.Value;
}
}
public IEnumerable<TValue> AllSubstringValues(String s)
{
int i_cur = 0;
while (i_cur < s.Length)
{
TrieNode<TValue> node = _root;
int i = i_cur;
while (i < s.Length)
{
node = node[s[i]];
if (node == null)
break;
if (node.Value != null)
yield return node.Value;
i++;
}
i_cur++;
}
}
};
Here's the right syntax:
if(names.Contains(myName))
{
//success code//
}
if (names.Contains(myName))
{
//success code//
}

Resources