用列表条目替换字符串出现

时间:2015-07-16 11:12:11

标签: c# string

我一直围着这个寻找一个“优雅”的解决方案,但我对此并不十分满意。

可能的输入字符串:

foo () bar ()

() bar

foo

()()foo () bar

括号中可以有“无限”括号和可选的非括号文本。这些空括号的内容应该填充来自列表条目顺序的List<string>的数据。如果没有条目或没有足够的条目,则括号不受影响。

可能的字符串替换:

foo () bar ()替换的

x, y将导致foo (x) bar (y)

foo () bar ()替换的

x将导致foo (x) bar ()

foo () bar ()替换的

x, y, z将导致foo (x) bar (y)

我希望你明白这一点。

解决方案: 到目前为止,我所拥有的解决方案正在摆弄索引和许多特殊逻辑来处理不同的情况。

我想知道是否有更优雅的解决方案,例如正则表达式。也许我现在对这个问题太近了,而且有一个简单的解决方案: - )

这是一种我并不高兴的方法(可读性/易于理解):

  var guiIdentifierIndex = 0;
  var guiIdentifierList = new List<string>{"x", "y", "z", "x", "y"};

  var sourcePathItem = "foo ()";
  string targetString = "";
  var splittedPath = sourcePathItem.Split(new string[] { BRACKETS }, StringSplitOptions.None);
  for (int index = 0; index < splittedPath.Length; index++)
  {
    var subPath = splittedPath[index];
    var guiIdentifier = string.Empty;
    if (guiIdentifierIndex < guiIdentifierList.Count)
    {
      guiIdentifier = guiIdentifierList[guiIdentifierIndex];
      guiIdentifierIndex++;
    }
    targetString += subPath;
    if (index < splittedPath.Length - 1)
      targetString += string.Format("({0})", guiIdentifier);
  }

http://volatileread.com/utilitylibrary/snippetcompiler?id=22718

7 个答案:

答案 0 :(得分:1)

您可以使用正则表达式,例如

  String source = "foo () bar ()";

  var guiIdentifierList = new List<String> { 
    "x", "y", "z", "x", "y" };

  int guiIdentifierIndex = 0; 

  // result == "foo (x) bar (y)"
  String result = Regex.Replace(source, @"\(\)", (MatchEvaluator) (
    (match) => "(" + (guiIdentifierIndex < guiIdentifierList.Count 
                      ? guiIdentifierList[guiIdentifierIndex++] 
                      : "") + ")"
  ));

答案 1 :(得分:0)

在逗号上拆分替换字符串(x,y,z),然后遍历生成的数组,用适当的值替换第一次出现的()。

此链接显示如何替换第一个实例:Replace first occurrence of pattern in a string

答案 2 :(得分:0)

这个怎么样:

var template = "foo () bar ()";
var replacements = new[] {"x", "y", "z"};

var components = template.Split(new []{"()"}, StringSplitOptions.RemoveEmptyEntries);
var sb = new StringBuilder();

var replacementCount = replacements.Count();

for (int i = 0; i < components.Count(); i++)
{
    var value = i >= replacementCount ? String.Empty : replacements[i];
    sb.AppendFormat("{0}({1})", components[i], value);
}

var substitutedTemplate = sb.ToString();

答案 3 :(得分:0)

var numbers = new List<string>(new[] { "1", "2", "3" });
string original = "() test ()()";

String[] tokens = original.Split(new [] {"()"}, StringSplitOptions.None);

if (tokens.Count() >= numbers.Count())
    return original;

return string.Concat(tokens.Take(tokens.Count() - 1)
                           .Select((t, i) => t + "(" + numbers[i] + ")"));

答案 4 :(得分:0)

您可以尝试在这样的一个foor循环中构建目标字符串(&#34;复制和替换&#34;)

编辑:现在用#34; lookahead&#34;如果缺少右括号,则无法替代。

var guiIdentifierIndex = 0;
var guiIdentifierList = new List<string> { "x", "y", "z" };

var sourcePathItem = "foo () bar () func()";
string targetString = "";
int srcIndex = 0;

foreach(char c in sourcePathItem)
{
    targetString += c;
    char lookahead = srcIndex < sourcePathItem.Length - 1 ? sourcePathItem[++srcIndex] : ' ';

    if (c == '(' && lookahead == ')' 
        && guiIdentifierIndex < guiIdentifierList.Count)
    {
        targetString += guiIdentifierList[guiIdentifierIndex++];
    }
}
Console.WriteLine("Target: " + targetString);

这会将foo () bar ()替换为x, yfoo (x) bar (y)

通常我认为当StringbuildersourcePathItem越来越大时,使用guidIdentifierList作为目标字符串会更好。例如资源使用量减少

问候

答案 5 :(得分:0)

我会这样做:

System.InvalidOperationException: Specified element is already the logical child of another element. Disconnect it first.
  at System.Windows.FrameworkContentElement.ChangeLogicalParent(DependencyObject newParent)
  at System.Windows.FrameworkElement.AddLogicalChild(Object child)
  at DevExpress.Xpf.Bars.PopupMenu.DevExpress.Xpf.Bars.ILinksHolder.OnLinkAdded(BarItemLinkBase link)
  at DevExpress.Xpf.Bars.BarItemLinkCollection.UpdateItemLinkOnAddToCollection(BarItemLinkBase itemLink)
  at DevExpress.Xpf.Bars.BarItemLinkCollection.InsertItem(Int32 index, BarItemLinkBase itemLink)
  at DevExpress.Xpf.Bars.CustomizablePopupMenuBase.CustomizablePopupMenuItemLinkCollection.InsertItem(Int32 index, BarItemLinkBase itemLink)
  at System.Collections.ObjectModel.Collection`1.Add(T item)
  at DevExpress.Xpf.Bars.BarItemLinkBase.DevExpress.Xpf.Bars.IBarManagerControllerAction.Execute()
  at DevExpress.Xpf.Bars.BarManagerActionCollection.Execute()
  at DevExpress.Xpf.Bars.BarManagerActionContainer.Execute()
  at DevExpress.Xpf.Bars.BarManagerController.Execute()
  at DevExpress.Xpf.Bars.BarManagerMenuController.Execute()
  at DevExpress.Xpf.Grid.DataControlPopupMenu.ExecuteOriginationViewMenuController(Func`2 getMenuController)
  at DevExpress.Xpf.Grid.GridCellMenuInfo.ExecuteMenuController()
  at DevExpress.Xpf.Bars.CustomizablePopupMenuBase.CreateItems()
  at DevExpress.Xpf.Bars.CustomizablePopupMenuBase.RaiseOpening()
  at DevExpress.Xpf.Bars.BarPopupBase.OnIsOpenCoerce(Object value)
  at DevExpress.Xpf.Bars.PopupMenuBase.OnIsOpenCoerce(Object value)
  at DevExpress.Xpf.Bars.CustomizablePopupMenuBase.OnIsOpenCoerce(Object value)
  at DevExpress.Xpf.Bars.BarPopupBase.OnIsOpenCoerce(DependencyObject d, Object value)
  at System.Windows.DependencyObject.ProcessCoerceValue(DependencyProperty dp, PropertyMetadata metadata, EntryIndex& entryIndex, Int32& targetIndex, EffectiveValueEntry& newEntry, EffectiveValueEntry& oldEntry, Object& oldValue, Object baseValue, Object controlValue, CoerceValueCallback coerceValueCallback, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, Boolean skipBaseValueChecks)
  at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
  at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
  at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value)
  at System.Windows.Controls.Primitives.Popup.set_IsOpen(Boolean value)
  at DevExpress.Xpf.Bars.ContextMenuManager.ShowElementContextMenu(Object contextElement, Boolean openingFromKeyboard)
  at DevExpress.Xpf.Bars.ContextMenuManager.OpenContextMenu(Object sender, Boolean openingFromKeyboard)
  at DevExpress.Xpf.Bars.ContextMenuManager.OnContextMenuOpening(Object sender, ContextMenuEventArgs e)
  at System.Windows.Controls.ContextMenuEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
  at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
  at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
  at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
  at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
  at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
  at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
  at System.Windows.Controls.PopupControlService.RaiseContextMenuOpeningEvent(IInputElement source, Double x, Double y, Boolean userInitiated)
  at System.Windows.Controls.PopupControlService.ProcessMouseUp(Object sender, MouseButtonEventArgs e)
  at System.Windows.Controls.PopupControlService.OnPostProcessInput(Object sender, ProcessInputEventArgs e)
  at System.Windows.Input.InputManager.RaiseProcessInputEventHandlers(ProcessInputEventHandler postProcessInput, ProcessInputEventArgs processInputEventArgs)
  at System.Windows.Input.InputManager.ProcessStagingArea()
  at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
  at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
  at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
  at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
  at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
  at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
  at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
  at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
  at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)


  System.InvalidOperationException: Specified element is already the logical child of another element. Disconnect it first.
     at System.Windows.FrameworkContentElement.ChangeLogicalParent(DependencyObject newParent)
     at System.Windows.FrameworkElement.AddLogicalChild(Object child)
     at DevExpress.Xpf.Bars.PopupMenu.DevExpress.Xpf.Bars.ILinksHolder.OnLinkAdded(BarItemLinkBase link)
     at DevExpress.Xpf.Bars.BarItemLinkCollection.UpdateItemLinkOnAddToCollection(BarItemLinkBase itemLink)
     at DevExpress.Xpf.Bars.BarItemLinkCollection.InsertItem(Int32 index, BarItemLinkBase itemLink)
     at DevExpress.Xpf.Bars.CustomizablePopupMenuBase.CustomizablePopupMenuItemLinkCollection.InsertItem(Int32 index, BarItemLinkBase itemLink)
     at System.Collections.ObjectModel.Collection`1.Add(T item)
     at DevExpress.Xpf.Bars.BarItemLinkBase.DevExpress.Xpf.Bars.IBarManagerControllerAction.Execute()
     at DevExpress.Xpf.Bars.BarManagerActionCollection.Execute()
     at DevExpress.Xpf.Bars.BarManagerActionContainer.Execute()
     at DevExpress.Xpf.Bars.BarManagerController.Execute()
     at DevExpress.Xpf.Bars.BarManagerMenuController.Execute()
     at DevExpress.Xpf.Grid.DataControlPopupMenu.ExecuteOriginationViewMenuController(Func`2 getMenuController)
     at DevExpress.Xpf.Grid.GridCellMenuInfo.ExecuteMenuController()
     at DevExpress.Xpf.Bars.CustomizablePopupMenuBase.CreateItems()
     at DevExpress.Xpf.Bars.CustomizablePopupMenuBase.RaiseOpening()
     at DevExpress.Xpf.Bars.BarPopupBase.OnIsOpenCoerce(Object value)
     at DevExpress.Xpf.Bars.PopupMenuBase.OnIsOpenCoerce(Object value)
     at DevExpress.Xpf.Bars.CustomizablePopupMenuBase.OnIsOpenCoerce(Object value)
     at DevExpress.Xpf.Bars.BarPopupBase.OnIsOpenCoerce(DependencyObject d, Object value)
     at System.Windows.DependencyObject.ProcessCoerceValue(DependencyProperty dp, PropertyMetadata metadata, EntryIndex& entryIndex, Int32& targetIndex, EffectiveValueEntry& newEntry, EffectiveValueEntry& oldEntry, Object& oldValue, Object baseValue, Object controlValue, CoerceValueCallback coerceValueCallback, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, Boolean skipBaseValueChecks)
     at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
     at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
     at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value)
     at System.Windows.Controls.Primitives.Popup.set_IsOpen(Boolean value)
     at DevExpress.Xpf.Bars.ContextMenuManager.ShowElementContextMenu(Object contextElement, Boolean openingFromKeyboard)
     at DevExpress.Xpf.Bars.ContextMenuManager.OpenContextMenu(Object sender, Boolean openingFromKeyboard)
     at DevExpress.Xpf.Bars.ContextMenuManager.OnContextMenuOpening(Object sender, ContextMenuEventArgs e)
     at System.Windows.Controls.ContextMenuEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
     at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
     at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
     at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
     at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
     at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
     at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
     at System.Windows.Controls.PopupControlService.RaiseContextMenuOpeningEvent(IInputElement source, Double x, Double y, Boolean userInitiated)
     at System.Windows.Controls.PopupControlService.ProcessMouseUp(Object sender, MouseButtonEventArgs e)
     at System.Windows.Controls.PopupControlService.OnPostProcessInput(Object sender, ProcessInputEventArgs e)
     at System.Windows.Input.InputManager.RaiseProcessInputEventHandlers(ProcessInputEventHandler postProcessInput, ProcessInputEventArgs processInputEventArgs)
     at System.Windows.Input.InputManager.ProcessStagingArea()
     at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
     at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
     at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
     at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
     at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
     at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
     at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
     at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
     at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)

请注意,分裂是一个不规则的动词,第三种形式也是分裂,分裂是非常奇怪的,我不建议你使用。

答案 6 :(得分:-1)

 StringBuilder sb = new StringBuilder();
 String[] parts = sourcePathItem.Split(new String[]{"()"}, StringSplitOptions.None);

 for (Int32 i = 0; i < parts.Length; i++){
      sb.Append(parts[i]);
      if (i < guiIdentifierList.Count && i + 1 < parts.Length)
          sb.Append("(" + guiIdentifierList[i] + ")");
 }

 var result = sb.ToString();