2017-09-29 22 views
0

テキストファイルから姓と名を読み取るプログラムを作成する必要があります。次に、名字の4文字と姓の4文字をとり、それらを3番目の文字列に結合する必要があります。問題は、新しい文字列が一意でなければならないということです。例えば、 。一意の文字列を作成するC#

まず名前=ジェームズ 姓=ジャクソン

新しい文字列がJAMEJACK

まず名前=ジェームズ 姓=ジャック

新しい文字列= JAMEJACK1 たり、新しい文字列になります= JAMSJACK

すべての文字列が一意である限り、どのように行われるかは関係ありません。

 LastName = input.Substring(12, 10); 

     FirstName = input.Substring(21, 21); 
     new string = LastName.Substring(0, 4) + FirstName.Substring(0, 4); 

これはおそらくこれを実行する最良の方法ではありませんが、私はまだこれで新しいです。

ご意見やご提案があれば幸いです。 ありがとうございます。

+1

名前が4文字未満の場合はどうなりますか? – Fran

+0

それはちょうどそこにあるものを使うでしょう。長さはそれほど重要ではありません。ただ一意である必要があります。 – imsohappy

+0

データセットを知らなくても、何がユニークになるのかわかる方法はありません。一意性を保証するために乱数を追加するだけではない理由はありますか? – Amy

答えて

0

サム・マリオンが本当にあるために、ここでのクレジットを取得提案する最初のそれは私が持っていたのと同じ考え方だった。

Dictionary<string, int>を使用して、すべての結合名とそこに含まれる数の数を保存してみませんか?その後、ディクショナリを作成した後は、重複数だけ数字を増やすことができます。このような何か:

Dictionary<string, int> usernameCollection = new Dictionary<string, int>(); 

foreach(string name in namesTextFile) 
{ 
    string username = string.Concat(name.Split().Select(x => x.Length >= 4 ? x.Substring(0, 4) : x)); 

    if(usernameCollection.ContainsKey(username)) 
    { 
     usernameCollection[username] = usernameCollection[username] + 1; 
    } 
    else 
    { 
     usernameCollection.Add(username, 1); 
    }     
} 

私は証明するためにフィドルhereを作りました。

+1

編集:申し訳ありませんが、私はフィドルを誤解しました。叫んでいただきありがとうございます。いい答えだ! –

+1

私がdownvotedされた理由を聞くのが大好き... – maccettura

+0

@maccettura私はファイルから文字列を読む必要があるときに私はあなたの提案を使用すると思いますか? – imsohappy

1

このコードは、このトリックを行う必要があります。私はそれにいくつかのコメントを追加し、私ができるほどシンプルに説明しようとしました。

var uniqueList = new HashSet<string>(); 

for (int i = 0; i < 4; i++) //just for testing purposes 
{ 
    string firstName = "James"; //first name 
    string lastName = "Jackson"; //last name 

    string shortFN = (firstName.Length >= 4) ? firstName.Substring(0, 4) : firstName; //check for name with 4 or less chars 
    string shortLN = (lastName.Length >= 4) ? lastName.Substring(0, 4) : lastName; //with "true", it uses the whole name 

    string newShortName = shortFN + shortLN; //adding up the words 

    if (uniqueList.Contains(newShortName)) //find if its unique to the list of names 
    { 
     //not unique 
     var repeatedNames = uniqueList.Count(x => x.Contains(newShortName)); //this will get how many names in the list are repeated 
     newShortName += repeatedNames; //we add the number 
     uniqueList.Add(newShortName); //now the name is unique, so we add it 
    } 
    else 
    { 
     uniqueList.Add(newShortName); //adding the new name to the list of names 
    } 
} 
+0

あなたの解決策は、文字列の最後に '1'を追加し続けることです。 – maccettura

+0

まあ、私はちょうどそれが繰り返される名前の数に応じて数字を追加する必要があることをお読みください。私の答えを更新しようとしましょう。 – FireFrog

+2

'List 'ではなく、 'HashSet 'と考えるといいかもしれません。 'HashSet.Contains'は' List.Find'よりもはるかに速くなければなりません... – Chris

0

以前のエントリと比較できなくても一意性を保証することはできません。

私が考えている最も簡単な方法は、あなたが作成した各エントリをリストに入力し、新しいエントリを作成するときにリストの他のすべてのエントリと一意性を比較し、

これを行うには、より効率的な方法があることは間違いありませんが、ここでは単純な答えが良いと思います。あなたのために、この作品のような

List<string> CompareList = new List<string>(); 
     //...however you're gonna loop this 

     string LastName = input.Substring(12, 10); 

     string FirstName = input.Substring(21, 21); 
     string generatedName = LastName.Substring(0, 4) + 
           FirstName.Substring(0, 4); 
     bool nameIsUnique = true; 

     foreach (var entry in CompareList) 
     { 
      if (entry == generatedName) nameIsUnique = false; 
     } 

     if (nameIsUnique) CompareList.Add(generatedName); 
     else //Go back to generating a name, add a number on the end, etc 
     //Go to next line in your text file, rinse, repeat. 
0

なりの何か:

は、ここでの擬似コードの例ですか?

var result = grouped.SelectMany(x => 
    { 
     var uniqueNames = new List<string>(); 

     var index = 1; 

     foreach (var singleName in x) 
     { 
      uniqueNames.Add($"{singleName.FirstName}{singleName.LastName}{index++}"); 
     } 

     return uniqueNames; 
    }); 

しかしがわずかに異なる結果を生成します:

AAABBB1 
AAABBB2 
CCCDDD 

それとももっと簡単:結果

var names = new List<Name> 
    { 
     new Name { FirstName = "AAA", LastName = "BBB" }, 
     new Name { FirstName = "AAA", LastName = "BBB" }, 
     new Name { FirstName = "CCC", LastName = "DDD" } 
    }; 

    var trimmedNames = names.Select(x => new Name { FirstName = x.FirstName.Substring(0, 4), LastName = x.LastName.Substring(0, 4) }); 

    var grouped = trimmedNames.GroupBy(x => new { x.FirstName, x.LastName }); 
    var result = grouped.SelectMany(x => 
    { 
     var uniqueNames = new List<string>(); 

     if (x.Count() > 1) 
     { 
      var index = 1; 

      foreach (var singleName in x) 
      { 
       uniqueNames.Add($"{singleName.FirstName}{singleName.LastName}{index++}"); 
      } 
     } 
     else 
     { 
      uniqueNames.Add($"{x.Key.FirstName}{x.Key.LastName}"); 
     } 

     return uniqueNames; 
    }).ToList(); 

AAABBB1 
AAABBB2 
CCCDDD1 
+1

これは4文字未満の文字列には適していますが、4文字以上のチェック文字列はありません。 –

+0

@SamMarion申し訳ありませんが、私は従いません。 –

+0

要件は、姓または名を4文字の長さに調整することでした。あなたの例では、ユーザーがすでにそれを行っていると仮定していますが、それはあなたの答えに追加するのが良いでしょう。 –

-1

私はGUIDオプションが好きです。姓と名の4文字をシードの一部として使用できます。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace randomseed 
{ 
class Program 
{ 
    static void Main(string[] args) 
    { 
     string first = "fir"; 
     string last = "LastName"; 
     string firstlast = first.Substring(0, first.Length > 4 ? 4 : first.Length) 
      + last.Substring(0, last.Length > 4 ? 4 : last.Length); 
     int seed = 0; 
        string uniqueString = firstlast + GenerateStringNameGuid(seed); 
     string u2 = firstlast + GenerateStringNameGuid(seed); 
     string u3 = firstlast + GenerateStringNameGuid(seed); 

     Console.Write($"uniqueString = { uniqueString} \n"); 
     Console.Write($"uniqueString = { u2} \n"); 
     Console.Write($"uniqueString = { u3} \n"); 



    } 

    public static string GenerateStringNameGuid(int seed) 
    { 
     var r = new Random(seed + Guid.NewGuid().GetHashCode()); 
     var guid = new byte[16]; 
     r.NextBytes(guid); 

     return new Guid(guid).ToString(); 
    } 
} 

}

出力

uniqueString = firLast7e7d1ec5-a375-3384-7e39-89859fa55d6f 
uniqueString = firLast047f91be-3f7c-e0aa-414e-ece64bf6833f 
uniqueString = firLast00042b27-0afa-fd92-c127-95bd84235040 
+0

これはOPの問題をまったく解決しません。最初と最後の名前の最初の4文字(または名前が4文字でない場合はそれ以下)を結合し、重複したエントリの最後に(1、2、3など)を追加する名前のリストが必要です。 – maccettura

+0

ちょうど今それを追加する –

+1

また、私は推測する場所(私は間違っている可能性があります)これは一意のユーザー名を作成するための何かのようです。私はユーザーがそれらの名前でログインしていただければと思っていません...それ以外の場合は完全に動作し、大丈夫です。 –

0

私は少し遅れて相手にだ知っているが、これは、@ maccetturaの答えのバージョンです。直接部分文字列をとるのではなく、これは名字の部分文字列をランダムに構成し、それでも一意の場合はカウントを追加します。

public class Program 
{ 
    // Take distinct set of random numbers in a given range 
    public static List<int> GetDistinctRandomNumbers(int min, int max, int count) 
    { 
     // Must do error checks for if (min > max) etc... 
     var rnd = new Random(); 
     var val = Enumerable.Range(min, max).OrderBy(x => rnd.Next()); 
     return val.Take(count).ToList(); 
    } 

    // Get a substring of a string composed by extracting characters from given indices 
    public static string GetStringByIndices(string str, List<int> indexes) 
    { 
     string result = string.Empty; 
     foreach (var index in indexes) 
      result += str[index]; 
     return result; 
    } 

    public static string CreateRandomString(string str1, string str2) 
    { 
     // Number of characters to extract from each string 
     int len1 = (str1.Length < 4) ? str1.Length : 4; 
     int len2 = (str2.Length < 4) ? str2.Length : 4; 

     // Indices at which characters will be extracted from each string 
     var str1Indexes = GetDistinctRandomNumbers(0, str1.Length, len1); 
     var str2Indexes = GetDistinctRandomNumbers(0, str2.Length, len2); 

     // Extracted strings 
     var first = GetStringByIndices(str1, str1Indexes); 
     var second = GetStringByIndices(str2, str2Indexes); 

     // Potentially unique string 
     return first + second; 
    } 

    public static void CreateUniqueList(string strToAdd, ref Dictionary<string,int> dict) 
    { 
     if (!dict.ContainsKey(strToAdd)) 
      dict.Add(strToAdd, 1); // If not found in the dictionary, add it, with a count of 1 
     else 
     { 
      int count; 
      if (dict.TryGetValue(strToAdd, out count)) 
      { 
       dict.Add(strToAdd + count.ToString(), count + 1); // If found, add a new item where NewKey = ExistingKey + Count 
       dict[strToAdd] += 1; // Increment count of existing Key 
      } 
     } 
    } 

    public static void Main() 
    { 
     Dictionary<string, int> unique = new Dictionary<string, int>(); 

     for (int i = 0; i < 20; i++) 
     { 
      var str = CreateRandomString("Jennifer", "Lawrence"); 
      CreateUniqueList(str, ref unique); 
     } 

     Console.ReadLine(); 
    } 
} 

確かにこれは本当にあなたが任意の特定の利点を与える(私は推測)、それだけでこのことを楽しみ書いていたしません。

+0

メソッドの外側で 'var rnd = new Random();'を移動して、繰り返し値を取得しないようにする必要があります。 – Enigmativity

関連する問題