2014-02-13 13 views
8

ich für eine Methode suchen, die zwei Strings nehmen und die Anzahl der Zeichen zurück, die sowohl zB gemeinsam sind:Suche Anzahl der Zeichen gegenseitigen zwischen zwei Strings in C#

„G010“ & „G1820A“ soll zurückkehren 3 als die G, 0 und 1 Zeichen existieren in beiden.

Wenn ein char existiert zweimal in beide sollten sie getrennt gezählt werden, wie folgt:

"G12AA" & "GAA2" 4 als G, A zurückkehren sollte, A und 2-Zeichen existieren in beiden.

Irgendwelche Hilfe dabei? Google-Suchen waren bisher nicht sehr hilfreich.

+3

Könnte klassisch sein, aber hast du _anything_ bisher versucht? –

+0

Ich habe eine Methode, die zwei Zeichenfolgen für Ähnlichkeiten vergleicht, aber mit den Zeichen in den gleichen Indizes, dies ist jedoch völlig anders. – Tommy

+0

"G12AA" & "GA2" sollte 4 zurückgeben? und "GA2" & "G12AA" sollte 4 zurückgeben? –

Antwort

-3

Bitte überprüfen Sie folgenden Code -> src ist erste Saite während chk zweiten String count = 0

var ist; var i = 0; . src.ToList() FürJeden ((x) => {
while (chk.Substring (i) .IndexOf (x)> = 0) {
Zählung ++; i ++; if (i> CHK. Länge) Pause; }
});

+1

Was ist mit AA und A? –

+3

Immer noch nicht wissen, wie man eine Antwort nach 194 Antworten formatiert? –

+0

Was ist 'ich'? .. – I4V

4

Versuchen Sie, diese

public int CommonCharacters(string s1, string s2) 
    { 
     bool[] matchedFlag = new bool[s2.Length]; 

     for (int i1 = 0; i1 < s1.Length; i1++) 
     { 
      for (int i2 = 0; i2 < s2.Length; i2++) 
      { 
       if (!matchedFlag[i2] && s1.ToCharArray()[i1] == s2.ToCharArray()[i2]) 
       { 
        matchedFlag[i2] = true; 
        break; 
       } 
      } 
     } 

     return matchedFlag.Count(u => u); 
    } 
+1

+1 und 'zurück matchedFlag.Count (b => b);' –

+1

Die Reihenfolge der Anweisungen in Ihrem Zustand umkehren, um die Effizienz zu verbessern: Kein Punkt, der all diese zusätzliche Arbeit erledigt Ändern von Strings in Arrays, wenn das Flag bedeutet, dass es sowieso nicht verwendet wird! – Nathan

+1

Ich meine, ändere die Reihenfolge der Bedingungen: if (s1 [i1] == s2 [i2] &&! MatchedFlag [i2]): effizienter zu prüfen, die boolesche zuerst: zu ändern, wenn (! MatchedFlag [i2] && s1 i1] == s2 [i2]) - siehe "short-circuiting" :) (fraglich, wie groß der Unterschied ist, den man jetzt macht, wenn man den String-Indexer für die erste Bedingung richtig benutzt) - müsste sehr groß sein Dataset - aber ich mache immer einen Punkt, um die einfachste Bedingung am Anfang einer if-Anweisung zu setzen, die && verwendet: kann einen wesentlichen Unterschied machen, besonders innerhalb mehrerer Schleifen. – Nathan

1

Sie Linq verwenden könnte, dieses Problem zu lösen, indem sie so etwas wie dies mit:

static void Main(string[] args) 
{ 
    IEnumerable<char> a = "G010".ToCharArray(); 
    IEnumerable<char> b = "G1820A".ToCharArray(); 

    int commonChars = FindCommonElements(a, b).Count(); 
    Console.WriteLine(commonChars); 

    Console.ReadLine(); 
} 

private static T[] FindCommonElements<T>(IEnumerable<T> source, IEnumerable<T> target) 
{ 
    ILookup<T, T> lookup2 = target.ToLookup(i => i); 

    return (
     from group1 in source.GroupBy(i => i) 
     let group2 = lookup2[group1.Key] 
     from i in (group1.Count() < group2.Count() ? group1 : group2) 
     select i 
    ).ToArray(); 
} 

commonChars einen Wert von 3. Die FindCommonElements Methode inspiriert haben durch diese Frage: How do I do an integer list intersection while keeping duplicates?

+0

Sie können 'Zip' verwenden, wie in meiner Antwort, um das vollständige Zählen beider Gruppen zu vermeiden. http://StackOverflow.com/a/21751976/659190 – Jodrell

+0

Sie haben Recht, intelligente Lösung. Du hast meine +1 – Vincent

1
 string s1 = "G12A"; 
     string s2 = "GAA2"; 
     List<char> lst1 = s1.ToList(); 
     List<char> lst2 = s2.ToList(); 
     int count = 0; 
     foreach (char c in lst2) 
     { 
      if (lst1.Contains(c)) 
      { 
       lst1.Remove(c); 
       count++; 
      } 
     } 
     Console.WriteLine(count); 
+0

Was bekommst du mit 'string s1 =" G12A ";'? –

+0

.............. 4 – Nathan

+0

Und es ist falsch. –

0

Dieser würde schneller mit größeren Eingaben laufen, da es keine Verschachtelungsschleifen macht, sondern eher von einer Hash-Suche mit dem Dictionary abhängt. Auf der anderen Seite verwendet es mehr Speicher.

public int CommonCharacterCount(string s1, string s2) 
      { 
       var r=0; 
       Dictionary<char,int> s2Dict = new Dictionary<char,int>(); 
       foreach (var ch in s2) 
       { 
        if (s2Dict.ContainsKey(ch)) 
         s2Dict[ch] = s2Dict[ch]+1; 
        else s2Dict.Add(ch,1); 
       } 

       foreach (var c in s1) 
       { 
        if (s2Dict.ContainsKey(c) && s2Dict[c]>0) 
        { 
         r++; 
         s2Dict[c] = s2Dict[c] - 1; 
        } 
       } 
       return r; 
      } 
1

tun es mit Linq:

int MyCount(string s1, string s2) 
    { 
     return s1.Count(c => 
          { 
           var i = s2.IndexOf(c); 
           if (i >= 0) 
           { 
            s2 = s2.Remove(i, 1); 
            return true; 
           } 
           return false; 
          }); 
    } 
3

Okay, wie wäre es damit, den Vorteil der Maximierung lazy evaluation hat und String-Manipulation zu minimieren.

essentialally, es gruppiert jede Seite von char, dann findet Zeichen, die eine Gruppe auf beiden Seiten haben. Die übereinstimmenden Gruppen werden im Tandem gezählt, bis einer der beiden ausläuft. Diese Zählungen werden summiert, um das Ergebnis zu erzeugen.


Es wäre trivial, dies generisch für jede zwei Sequenzen durchzuführen. Siehe unten,

public static int CommomCount<T>(
     this IEnumerable<T> source, 
     IEnumerable<T> sequence, 
     IEqualityComparer<T> comparer = null) 
{ 
    if (sequence == null) 
    { 
     return 0; 
    } 

    if (comparer == null) 
    { 
     comparer = EqualityComparer<T>.Default; 
    } 

    return source.GroupBy(t => t, comparer) 
     .Join(
      sequence.GroupBy(t => t, comparer), 
      g => g.Key, 
      g => g.Key, 
      (lg, rg) => lg.Zip(rg, (l, r) => l).Count(), 
      comparer) 
     .Sum(); 
} 

, die Sie mögen diese verwenden würden.

"G12AA".CommonCount("GAA2") 

Die optionalen comparer Parameter können nützlich sein, wenn Sie Groß- und Kleinschreibung oder andere spezielle Behandlung erfordern.


Im Interesse der resuability, würde ich ein IEnumerable<T> die Sum() und Rückkehr zu entfernen versucht sein, und dann Summe zum Anruf hinzufügen, wie diese,

public static IEnumerable<T> Commom<T>(
     this IEnumerable<T> source, 
     IEnumerable<T> sequence, 
     IEqualityComparer<T> comparer = null) 
{ 
    if (sequence == null) 
    { 
     return Enumerable.Empty<T>(); 
    } 

    if (comparer == null) 
    { 
     comparer = EqualityComparer<T>.Default; 
    } 

    return source.GroupBy(t => t, comparer) 
     .Join(
      sequence.GroupBy(t => t, comparer), 
      g => g.Key, 
      g => g.Key, 
      (lg, rg) => lg.Zip(rg, (l, r) => l), 
      comparer) 
     .SelectMany(g => g); 
} 

so könnte man leicht tun

Console.WriteLine(new string("G12AA".Common("GAA2").ToArray())); 

oder nur die orgininal

"G12AA".Common("GAA2").Count(); 
0
string myname = "1234"; 
     string yourname = "12"; 
     char[] sam = new char[] { }; 
     sam = myname.ToCharArray(); 
     char[] sam1 = new char[] { }; 
     sam1 = yourname.ToCharArray(); 
     int id = 0; 
     int id1 = 0; 
     List<string> found = new List<string>(); 
     List<string> found1 = new List<string>(); 
     foreach (char item in sam) 
     { 
      if (found.Contains(item.ToString())) 
      { 
       found.Add(item.ToString() + id); 
       id++; 
      } 
      else 
       found.Add(item.ToString()); 
     } 
     foreach (var item in sam1) 
     { 
      if (found1.Contains(item.ToString())) 
      { 
       found1.Add(item.ToString() + id); 
       id1++; 
      } 
      else 
       found1.Add(item.ToString()); 
     } 
     var final = found.Except(found1); 
     var final2 = found1.Except(found); 
     var checkingCount = final.Count() + final2.Count(); 
     Console.Write(checkingCount); 
     Console.ReadLine(); 

checken Sie das aus, btw nicht effizient. Aber hab es richtig gemacht.