Comment compter les occurrences de sous-chaîne? [dupliquer]

Cette question a déjà une réponse ici:

Supposons que j'ai une chaîne comme:

MyString = "OU=Level3,OU=Level2,OU=Level1,DC=domain,DC=com";

Ensuite, je veux savoir combien de temps d'occurrences de la sous-chaîne "OU=" dans cette chaîne. Avec char unique, peut-être il y a quelque chose comme:

int count = MyString.Split("OU=").Length - 1;

, Mais Split ne fonctionne que pour les char, pas string.

Aussi comment trouver la position de n occurrences? Par exemple, la position de 2ème "OU=" dans la chaîne?

Comment résoudre ce problème?

46
demandé sur BartoszKP 2013-03-22 22:31:56

8 réponses

Regex.Matches(input, "OU=").Count
114
répondu tnw 2013-03-22 18:35:36

Vous pouvez trouver toutes les occurrences et leurs positions avec IndexOf:

string MyString = "OU=Level3,OU=Level2,OU=Level1,DC=domain,DC=com";
string stringToFind = "OU=";

List<int> positions = new List<int>();
int pos = 0;
while ((pos < MyString.Length) && (pos = MyString.IndexOf(stringToFind, pos)) != -1)
{
    positions.Add(pos);
    pos += stringToFind.Length();
}

Console.WriteLine("{0} occurrences", positions.Count);
foreach (var p in positions)
{
    Console.WriteLine(p);
}

, Vous pouvez obtenir le même résultat à partir d'une expression régulière:

var matches = Regex.Matches(MyString, "OU=");
Console.WriteLine("{0} occurrences", matches.Count);
foreach (var m in matches)
{
    Console.WriteLine(m.Index);
}

Les principales différences:

  • le code Regex est plus court
  • le code Regex alloue une collection et plusieurs chaînes.
  • le code IndexOf peut être écrit pour afficher la position immédiatement, sans créer de collection.
  • il est probable que le code Regex sera plus rapide isolément, mais si utilisé plusieurs fois, la surcharge combinée des allocations de chaîne pourrait causer une charge beaucoup plus élevée sur le garbage collector.

Si j'écrivais ceci en ligne, comme quelque chose qui ne s'est pas habitué souvent, j'irais probablement avec la solution regex. Si je devais le mettre dans une bibliothèque comme quelque chose à utiliser beaucoup, j'irais probablement avec la solution IndexOf.

12
répondu Jim Mischel 2017-02-15 14:11:36

(trombine le trombone-mode:SUR)

On dirait que vous analysez une requête LDAP!

Voulez-vous l'analyser:

  • manuellement? Goto "SplittingAndParsing"
  • automagiquement via les appels Win32? Goto "utiliser Win32 via PInvoke"

(trombine le trombone-mode:OFF)

"Partage Et Analyse":

var MyString = "OU=Level3,OU=Level2,OU=Level1,DC=domain,DC=com";
var chunksAsKvps = MyString
    .Split(',')
    .Select(chunk => 
        { 
            var bits = chunk.Split('='); 
            return new KeyValuePair<string,string>(bits[0], bits[1]);
        });

var allOUs = chunksAsKvps
    .Where(kvp => kvp.Key.Equals("OU", StringComparison.OrdinalIgnoreCase));

"Utilisation de Win32 via PInvoke":

Utilisation:

var parsedDn = Win32LDAP.ParseDN(str);    
var allOUs2 = parsedDn
    .Where(dn => dn.Key.Equals("OU", StringComparison.OrdinalIgnoreCase));

Code D'Utilité:

// I don't remember where I got this from, honestly...I *think* it came
// from another SO user long ago, but those details I've lost to history...
public class Win32LDAP
{
   #region Constants
   public const int ERROR_SUCCESS = 0;
   public const int ERROR_BUFFER_OVERFLOW = 111;
   #endregion Constants

   #region DN Parsing
   [DllImport("ntdsapi.dll", CharSet = CharSet.Unicode)]
   protected static extern int DsGetRdnW(
       ref IntPtr ppDN, 
       ref int pcDN, 
       out IntPtr ppKey, 
       out int pcKey, 
       out IntPtr ppVal, 
       out int pcVal
   );

   public static KeyValuePair<string, string> GetName(string distinguishedName)
   {
       IntPtr pDistinguishedName = Marshal.StringToHGlobalUni(distinguishedName);
       try
       {
           IntPtr pDN = pDistinguishedName, pKey, pVal;
           int cDN = distinguishedName.Length, cKey, cVal;

           int lastError = DsGetRdnW(ref pDN, ref cDN, out pKey, out cKey, out pVal, out cVal);

           if(lastError == ERROR_SUCCESS)
           {
               string key, value;

               if(cKey < 1)
               {
                   key = string.Empty;
               }
               else
               {
                   key = Marshal.PtrToStringUni(pKey, cKey);
               }

               if(cVal < 1)
               {
                   value = string.Empty;
               }
               else
               {
                   value = Marshal.PtrToStringUni(pVal, cVal);
               }

               return new KeyValuePair<string, string>(key, value);
           }
           else
           {
               throw new Win32Exception(lastError);
           }
       }
       finally
       {
           Marshal.FreeHGlobal(pDistinguishedName);
       }
   }

   public static IEnumerable<KeyValuePair<string, string>> ParseDN(string distinguishedName)
   {
       List<KeyValuePair<string, string>> components = new List<KeyValuePair<string, string>>();
       IntPtr pDistinguishedName = Marshal.StringToHGlobalUni(distinguishedName);
       try
       {
           IntPtr pDN = pDistinguishedName, pKey, pVal;
           int cDN = distinguishedName.Length, cKey, cVal;

           do
           {
               int lastError = DsGetRdnW(ref pDN, ref cDN, out pKey, out cKey, out pVal, out cVal);

               if(lastError == ERROR_SUCCESS)
               {
                   string key, value;

                   if(cKey < 0)
                   {
                       key = null;
                   }
                   else if(cKey == 0)
                   {
                       key = string.Empty;
                   }
                   else
                   {
                       key = Marshal.PtrToStringUni(pKey, cKey);
                   }

                   if(cVal < 0)
                   {
                       value = null;
                   }
                   else if(cVal == 0)
                   {
                       value = string.Empty;
                   }
                   else
                   {
                       value = Marshal.PtrToStringUni(pVal, cVal);
                   }

                   components.Add(new KeyValuePair<string, string>(key, value));

                   pDN = (IntPtr)(pDN.ToInt64() + UnicodeEncoding.CharSize); //skip over comma
                   cDN--;
               }
               else
               {
                   throw new Win32Exception(lastError);
               }
           } while(cDN > 0);

           return components;
       }
       finally
       {
           Marshal.FreeHGlobal(pDistinguishedName);
       }
   }

   [DllImport("ntdsapi.dll", CharSet = CharSet.Unicode)]
   protected static extern int DsQuoteRdnValueW(
       int cUnquotedRdnValueLength,
       string psUnquotedRdnValue,
       ref int pcQuotedRdnValueLength,
       IntPtr psQuotedRdnValue
   );

   public static string QuoteRDN(string rdn)
   {
       if (rdn == null) return null;

       int initialLength = rdn.Length;
       int quotedLength = 0;
       IntPtr pQuotedRDN = IntPtr.Zero;

       int lastError = DsQuoteRdnValueW(initialLength, rdn, ref quotedLength, pQuotedRDN);

       switch (lastError)
       {
           case ERROR_SUCCESS:
               {
                   return string.Empty;
               }
           case ERROR_BUFFER_OVERFLOW:
               {
                   break; //continue
               }
           default:
               {
                   throw new Win32Exception(lastError);
               }
       }

       pQuotedRDN = Marshal.AllocHGlobal(quotedLength * UnicodeEncoding.CharSize);

       try
       {
           lastError = DsQuoteRdnValueW(initialLength, rdn, ref quotedLength, pQuotedRDN);

           switch(lastError)
           {
               case ERROR_SUCCESS:
                   {
                       return Marshal.PtrToStringUni(pQuotedRDN, quotedLength);
                   }
               default:
                   {
                       throw new Win32Exception(lastError);
                   }
           }
       }
       finally
       {
           if(pQuotedRDN != IntPtr.Zero)
           {
               Marshal.FreeHGlobal(pQuotedRDN);
           }
       }
   }


   [DllImport("ntdsapi.dll", CharSet = CharSet.Unicode)]
   protected static extern int DsUnquoteRdnValueW(
       int cQuotedRdnValueLength,
       string psQuotedRdnValue,
       ref int pcUnquotedRdnValueLength,
       IntPtr psUnquotedRdnValue
   );

   public static string UnquoteRDN(string rdn)
   {
       if (rdn == null) return null;

       int initialLength = rdn.Length;
       int unquotedLength = 0;
       IntPtr pUnquotedRDN = IntPtr.Zero;

       int lastError = DsUnquoteRdnValueW(initialLength, rdn, ref unquotedLength, pUnquotedRDN);

       switch (lastError)
       {
           case ERROR_SUCCESS:
               {
                   return string.Empty;
               }
           case ERROR_BUFFER_OVERFLOW:
               {
                   break; //continue
               }
           default:
               {
                   throw new Win32Exception(lastError);
               }
       }

       pUnquotedRDN = Marshal.AllocHGlobal(unquotedLength * UnicodeEncoding.CharSize);

       try
       {
           lastError = DsUnquoteRdnValueW(initialLength, rdn, ref unquotedLength, pUnquotedRDN);

           switch(lastError)
           {
               case ERROR_SUCCESS:
                   {
                       return Marshal.PtrToStringUni(pUnquotedRDN, unquotedLength);
                   }
               default:
                   {
                       throw new Win32Exception(lastError);
                   }
           }
       }
       finally
       {
           if(pUnquotedRDN != IntPtr.Zero)
           {
               Marshal.FreeHGlobal(pUnquotedRDN);
           }
       }
   }
   #endregion DN Parsing
}

public class DNComponent
{
   public string Type { get; protected set; }
   public string EscapedValue { get; protected set; }
   public string UnescapedValue { get; protected set; }
   public string WholeComponent { get; protected set; }

   public DNComponent(string component, bool isEscaped)
   {
       string[] tokens = component.Split(new char[] { '=' }, 2);
       setup(tokens[0], tokens[1], isEscaped);
   }

   public DNComponent(string key, string value, bool isEscaped)
   {
       setup(key, value, isEscaped);
   }

   private void setup(string key, string value, bool isEscaped)
   {
       Type = key;

       if(isEscaped)
       {
           EscapedValue = value;
           UnescapedValue = Win32LDAP.UnquoteRDN(value);
       }
       else
       {
           EscapedValue = Win32LDAP.QuoteRDN(value);
           UnescapedValue = value;
       }

       WholeComponent = Type + "=" + EscapedValue;
   }

   public override bool Equals(object obj)
   {
       if (obj is DNComponent)
       {
           DNComponent dnObj = (DNComponent)obj;
           return dnObj.WholeComponent.Equals(this.WholeComponent, StringComparison.CurrentCultureIgnoreCase);
       }
       return base.Equals(obj);
   }

   public override int GetHashCode()
   {
       return WholeComponent.GetHashCode();
   }
}

public class DistinguishedName
{
   public DNComponent[] Components
   {
       get
       {
           return components.ToArray();
       }
   }

   private List<DNComponent> components;
   private string cachedDN;

   public DistinguishedName(string distinguishedName)
   {
       cachedDN = distinguishedName;
       components = new List<DNComponent>();
       foreach (KeyValuePair<string, string> kvp in Win32LDAP.ParseDN(distinguishedName))
       {
           components.Add(new DNComponent(kvp.Key, kvp.Value, true));
       }
   }

   public DistinguishedName(IEnumerable<DNComponent> dnComponents)
   {
       components = new List<DNComponent>(dnComponents);
       cachedDN = GetWholePath(",");
   }

   public bool Contains(DNComponent dnComponent)
   {
       return components.Contains(dnComponent);
   }

   public string GetDNSDomainName()
   {
       List<string> dcs = new List<string>();
       foreach (DNComponent dnc in components)
       {
           if(dnc.Type.Equals("DC", StringComparison.CurrentCultureIgnoreCase))
           {
               dcs.Add(dnc.UnescapedValue);
           }
       }
       return string.Join(".", dcs.ToArray());
   }

   public string GetDomainDN()
   {
       List<string> dcs = new List<string>();
       foreach (DNComponent dnc in components)
       {
           if(dnc.Type.Equals("DC", StringComparison.CurrentCultureIgnoreCase))
           {
               dcs.Add(dnc.WholeComponent);
           }
       }
       return string.Join(",", dcs.ToArray());
   }

   public string GetWholePath()
   {
       return GetWholePath(",");
   }

   public string GetWholePath(string separator)
   {
       List<string> parts = new List<string>();
       foreach (DNComponent component in components)
       {
           parts.Add(component.WholeComponent);
       }
       return string.Join(separator, parts.ToArray());
   }

   public DistinguishedName GetParent()
   {
       if(components.Count == 1)
       {
           return null;
       }
       List<DNComponent> tempList = new List<DNComponent>(components);
       tempList.RemoveAt(0);
       return new DistinguishedName(tempList);
   }

   public override bool Equals(object obj)
   {
       if(obj is DistinguishedName)
       {
           DistinguishedName objDN = (DistinguishedName)obj;
           if (this.Components.Length == objDN.Components.Length)
           {
               for (int i = 0; i < this.Components.Length; i++)
               {
                   if (!this.Components[i].Equals(objDN.Components[i]))
                   {
                       return false;
                   }
               }
               return true;
           }
           return false;
       }
       return base.Equals(obj);
   }

   public override int GetHashCode()
   {
       return cachedDN.GetHashCode();
   }
}
6
répondu JerKimball 2013-03-22 18:50:41

Cette extension nécessite moins de ressources que les expressions regualr.

public static int CountSubstring(this string text, string value)
{                  
    int count = 0, minIndex = text.IndexOf(value, 0);
    while (minIndex != -1)
    {
        minIndex = text.IndexOf(value, minIndex + value.Length);
        count++;
    }
    return count;
}

Utilisation:

MyString = "OU=Level3,OU=Level2,OU=Level1,DC=domain,DC=com";
int count = MyString.CountSubstring("OU=");
3
répondu fubo 2014-08-22 09:08:20
int count = myString.Split(new []{','})
                    .Count(item => item.StartsWith(
                        "OU=", StringComparison.OrdinalIgnoreCase))
2
répondu Phil 2013-03-22 18:36:06

Ci-Dessous devrait fonctionner

  MyString = "OU=Level3,OU=Level2,OU=Level1,DC=domain,DC=com";
  int count = Regex.Matches(MyString, "OU=").Count
2
répondu ApolloSoftware 2013-03-22 18:38:49

Voici deux exemples de la façon dont vous pouvez obtenir les résultats que vous recherchez

var MyString = "OU=Level3,OU=Level2,OU=Level1,DC=domain,DC=com";

Celui - ci vous verriez une liste des valeurs séparées mais il aurait juste une idée de DC montre que la division avec la chaîne fonctionne`

var split = MyString.Split(new string[] { "OU=", "," }, StringSplitOptions.RemoveEmptyEntries);

Celui-ci va diviser et vous renvoyer seulement les 3 éléments dans une liste de sorte que si vous ne comptez pas sur un compte, vous pouvez valider visuellement qu'il renvoie les 3 niveaux de 'OU="

var lstSplit = MyString.Split(new[] { ',' })
        .Where(splitItem => splitItem.StartsWith(
               "OU=", StringComparison.OrdinalIgnoreCase)).ToList();
1
répondu MethodMan 2013-03-23 16:46:47
public static int CountOccurences(string needle, string haystack)
{
    return (haystack.Length - haystack.Replace(needle, "").Length) / needle.Length;
}

L'a comparé à d'autres réponses ici (la regex et la "IndexOf"), fonctionne plus rapidement.

0
répondu Serge Shultz 2015-05-20 07:59:57