increasing names in C# with integers - c#

I need to get an object and check if it already exists.
In case it does, I want to add a number, or increase the number in its name.
For example if I have the object "a" and it exists, I need to add a 1 so it's called a1.
In case a1 exists, a2, etc.
How could I perform this?
My code:
if (e.TreeNode.Tag is Variant)
{
if (variantExists(e.TreeNode.Text))
{
Random r = new Random();
int randomNumber = r.Next(0, 99);
e.TreeNode.Text = e.TreeNode.Text + randomNumber;
//e.TreeNode.Remove();
return;
}
}

Can you change the TreeNode class? I would add properties for Label (Name without Index) and Index and make the Name property read only, i.e
class TreeNode
{
public int Index {get;set;}
public string Label {get;set;}
public string Name
{
get { return Index == 0 ? Label : Label + Index; }
}
}
In your code you just need to set the Index property to the value you need and dont worry about the whole string parsing stuff

string name = "SomeName";
string tempName = name;
int n = 0;
while (DoesNameExist(tempName))
{
n++;
tempName = name + n;
}
name = tempName;
This gets ineffecient for large numbers of the same object, but that shouldn't happen right?
The problem with doing it the other way around, and stripping off trailing numbers to find the "original" name is that the original name may genuinely have numbers on it.
Eg. You say you add:
SomeName
SomeName99
SomeName
SomeName99
The above code will give you
SomeName
SomeName1
SomeName99
SomeName991

Something along the lines of this could work:
var existingItems = new HashSet<string>();
var items = new List<string>{"a", "b", "a"};
foreach (var item in items)
{
var tempItem = item;
var i = 1;
while (!existingItems.Add(tempItem))
tempItem = tempItem + i++;
}

Related

Add incremented number to string

I want to add a number to the end of a string.
eg.
john1
beth2
mike3
mary4
class finalName
{
public string name(string initialName)
{
string finalName = string.Empty;
for (int i = 1; i < 10; i++)
{
finalName = initialName + i.ToString("0");
}
return finalName;
}
}
finalName name = new finalName();
The result that I am getting is:
jonh9
beth9
mike9
mary9
What am I doing wrong?
What you want to do is modify your method so it takes a collection of names, then modifies those with an incrementing indexer:
public static IEnumerable<string> ModifyNames(IEnumerable<string> names)
{
int index = 1;
foreach (string name in names)
{
yield return name + index;
index++;
}
}
Fiddle here
You are just looping inside the method and returns the last value.
If you want each call of the function to add an incremented number, then add this counter as a field in your class and add it to the string:
int counter = 1;
public string name(string initialName)
{
return initialName + counter++;
}
If you are creating a new instance every call, then the variable should be made static:
static int counter = 1;
public string name(string initialName)
{
return initialName + counter++;
}
If you would like to send in a list of strings to the function and get back the list with an incremented number then you should first change the signature to get a collection and return a collection:
public IEnumerable<string> name(IEnumerable<string> names)
{
return names.Select( (s,i) => s+(i+1));
}
You should remove for loop from your name function.
Your loop always ends with i equal to 9 and result is always initialName + 9.
I think that you need something like this:
string[] names = new string[] { "john", "beth", "mike", "mary" };
for (int i = 0; i < names.Length; i++)
{
names[i] = names[i] + (i + 1).ToString();
}

select randomly from string array without repetitions

Good day I have some problem regarding selecting a random string from my string array I am currently developing a guessing word game.
this is my string array:
string[] movie = {"deadpool", "batmanvssuperman", "findingdory", "titanic", "suicidesquad", "lordoftherings", "harrypotter", "jurassicpark", "hungergames", "despicableme" };
while this is the process in selecting a random string to my array, what should i do next, because I want to select the string not repeated.
e.g
when the program starts it will select a string then when i select random string again i want to not select the previous word that i've already selected previously.
string word = movie[r.Next(0, movie.Length)].ToUpper();
Thank you for response! Have a nice day.
Well, simply convert your array to list and shuffle it in random order :
var rand = new Random();
string[] movies = { "deadpool", "batmanvssuperman", "findingdory", "titanic", "suicidesquad", "lordoftherings", "harrypotter", "jurassicpark", "hungergames", "despicableme" };
List<string> randomMovies = movies.ToList();
for (int i = 0; i < movies.Length / 2; i++)
{
var randNum = rand.Next(i, randomMovies.Count);
var temp = randomMovies[randNum];
randomMovies[randNum] = randomMovies[i];
randomMovies[i] = temp;
}
Then you can just take random elements by :
var randomMovie = randomMovies.First();
randomMovies.Remove(randomMovie); // either remove it or use loop to iterate through the list
I sort of like to use Queue collection here :
var moviesQueue = new Queue<string>(randomMovies);
while (moviewQueue.Count > 0)
{
Console.WriteLine(moviewQueue.Dequeue());
}
P.S.
As suggested you don't really need to delete elements from randomMovie, you can save last used index in some field and use it later;
var lastIndex = 0;
var randomMovie = randomMovies[lastIndex++];
Just loop if it's been selected. This is untested code:
private string _last;
private string GetNonRepeatedMovie()
{
string selected = "";
do
{
selected = movie[r.Next(0, movie.Length)].ToUpper();
}
while (selected == this._last);
this._last = selected;
return selected;
}
This should work to select the initial string as well when the application starts.
If you need to keep a memory, convert your list to be a class that contains the name and a field of whether it has been chosen or not.
If you go through all of them, turn this semiphor off and begin again.
class GuessingName
{
public GuessingName(string name){Name = name;}
public string Name;
public bool chosen;
}
class RandomNamePicker{
private List<GuessingName> names;
public RandomNamePicker(){
names = new List<GuessingName>();
names.Add(new GuessingName("movie"));
}
string RandomPicker(){
if(names.All(c=>c.chosen))
names.ForEach(c=>c.chosen=false);
int r1 = r.Next(0, names.Length);
while(names[r1].chosen){
r1= r.Next(0,names.Length);
}
return names[r1].Name;
}
}

C# : how do I correctly clone a List<> to onther

I have a two list one is original and other one is copy of original one
List<Button> buttonList; // this is the original list
List<Button> copyButtonList;// this is the copy of button list; this use to sort the list
I want to sort the copyButtonList according to my custom insertion sort where I written in separate class
I clone the original list to copy list following way(s) and sorted it
copyButtonList = buttonList.ToList();
String s = SortEngine.insertionSort(copyButtonList);
msgList.Items.Add(s);
I also try following ways
copyButtonList = new List<Button>(buttonList);
and
foreach (var b in buttonList) {
copyButtonList.Add(b);
}
after that I tried to print the two list as follows
foreach(var b in buttonList){
msgList.Items.Add(b.Text);
}
foreach(var b in copyButtonList){
msgList.Items.Add(b.Text);
}
in the above three situations both list are sorted :(
I want just sort the copyButtonList only, Can anyone point out the my mistakes I done here ?
Updated : my insertion sort algorithm is below
public static String insertionSort(List<Button> button)
{
String key;
int i = 0;
int j;
String s = "";
for (j = 1; j < button.Count; j++)
{
key = button.ElementAt(j).Text;
i = j - 1;
while (i >= 0 && int.Parse(button.ElementAt(i).Text) > int.Parse(key))
{
button.ElementAt(i + 1).Text = button.ElementAt(i).Text;
i = i - 1;
}
button.ElementAt(i + 1).Text = key;
if (i == -1)
{
s=(button.ElementAt(i + 1).Text + " is the starting Item, keep this in before " + button.ElementAt(i + 2).Text);
}
else if (i == j - 1)
{
s=(button.ElementAt(i + 1).Text + " is the last Item, keep this in after " + button.ElementAt(i).Text);
}
else
{
s=(button.ElementAt(i + 1).Text + " is between " + button.ElementAt(i).Text + " and " + button.ElementAt(i + 2).Text);
}
}
if (button.Count == 1)
{
s= ("This is the first Item");
}
return s;
}
Actually speising's question is not dumb.
Since you are not changing the Button there is not need for deep cloning.
Your problem is probably somewhere else.
Here is an example
public class Customer
{
public string Name { get; set; }
public override string ToString()
{
return Name;
}
}
public class CustomerComparer : IComparer<Customer>
{
public int Compare(Customer x, Customer y)
{
return x.Name.CompareTo(y.Name);
}
}
void Print()
{
List<Customer> l1 = new List<Customer>();
l1.Add(new Customer() { Name="aa"});
l1.Add(new Customer() { Name = "cc" });
l1.Add(new Customer() { Name = "bb" });
List<Customer> l2 = new List<Customer>(l1);
l2.Sort(new CustomerComparer());
foreach (var item in l1)
Console.WriteLine(item);
Console.WriteLine();
foreach (var item in l2)
Console.WriteLine(item);
Console.ReadLine();
}
This prints
aa
cc
bb
and then
aa
bb
cc
Update
Your ARE changing the button so you need a deep copy.Use this to create the new list
using System.Linq;
copyButtonList = buttonList.Select(ee => new Button() { Text= ee.Text}).ToList();
By "Changing the button" i mean lines like this
button.ElementAt(i + 1).Text = key;
You may have 2 lists but they both "point"/have the same objects.When you change the Text of a button in list 1 it means that the object is changed also in list 2.
You need to understand what is a value type and what is a reference type and their differences. Here are some links that will help you
http://www.albahari.com/valuevsreftypes.aspx
What is the difference between a reference type and value type in c#?
Also run the following console application on your pc and see what is printed
using System;
public struct Point
{
public int X;
public Point(int initialValue) { X = initialValue; }
}
class Program
{
static void Main(string[] args)
{
Point point1 = new Point(5);
Console.WriteLine("Before:" + point1.X);
ChangePoint(point1);
Console.WriteLine("After:" + point1.X);
Console.ReadLine();
}
private static void ChangePoint(Point p)
{
p.X = 20;
}
}
Then just change the word "struct" to "class" and see what is printed.
You get different result because structs are value types and classes are reference types.
Your sorting algorithm modifies the Buttons, which are the same in both lists. if you really want to do it that way, you need to deep copy the objects, ie. make copies or each button, not just their references.
but a much better solution to sort the list would be to just sort the list, ie. switch the elements indices. (like button[i+1]=button[i])
You can use method mentioned here
List<YourType> oldList = new List<YourType>();
List<YourType> newList = new List<YourType>(oldList.Count);
oldList.ForEach((item)=>
{
newList.Add(new YourType(item));
});

Get first value in CSV column without duplicates

I am getting a list of items from a csv file via a Web Api using this code:
private List<Item> items = new List<Item>();
public ItemRepository()
{
string filename = HttpRuntime.AppDomainAppPath + "App_Data\\items.csv";
var lines = File.ReadAllLines(filename).Skip(1).ToList();
for (int i = 0; i < lines.Count; i++)
{
var line = lines[i];
var columns = line.Split('$');
//get rid of newline characters in the middle of data lines
while (columns.Length < 9)
{
i += 1;
line = line.Replace("\n", " ") + lines[i];
columns = line.Split('$');
}
//Remove Starting and Trailing open quotes from fields
columns = columns.Select(c => { if (string.IsNullOrEmpty(c) == false) { return c.Substring(1, c.Length - 2); } return string.Empty; }).ToArray();
var temp = columns[5].Split('|', '>');
items.Add(new Item()
{
Id = int.Parse(columns[0]),
Name = temp[0],
Description = columns[2],
Photo = columns[7]
});
}
}
The Name attribute of the item list must come from column whose structure is as follows:
Groups>Subgroup>item
Therefore I use var temp = columns[5].Split('|', '>'); in my code to get the first element of the column before the ">", which in the above case is Groups. And this works fine.
However, I a getting many duplicates in the result. This is because other items in the column may be:
(These are some of the entries in my csv column 9)
Groups>Subgroup2>item2, Groups>Subgroup3>item4, Groups>Subgroup4>item9
All start with Groups, but I only want to get Groups once.
As it is I get a long list of Groups. How do I stop the duplicates?
I want that if an Item in the list is returned with the Name "Groups", that no other item with that name would be returned. How do I make this check and implement it?
If you are successfully getting the list of groups, take that list of groups and use LINQ:
var undupedList = dupedList
.Distinct();
Update: The reason distinct did not work is because your code is requesting not just Name, but also, Description, etc...If you only ask for Name, Distinct() will work.
Update 2: Try this:
//Check whether already exists
if((var match = items.Where(q=>q.Name == temp[0])).Count==0)
{
items.add(...);
}
How about using a List to store Item.Name?
Then check List.Contains() before calling items.Add()
Simple, only 3 lines of code, and it works.
IList<string> listNames = new List();
//
for (int i = 0; i < lines.Count; i++)
{
//
var temp = columns[5].Split('|', '>');
if (!listNames.Contains(temp[0]))
{
listNames.Add(temp[0]);
items.Add(new Item()
{
//
});
}
}

Sending a list of doubles as strings to the database

Just quite confused with the piece of code below.
I have class like below
public class Counter
{
public Double NormalCounter { get; set; }
public Double SATCounter { get; set; }
public Double SUNCounter { get; set; }
}
in my main class i have method to do some calculation to fill the counter
Counter CountHrs = GetBookedHours(resourceBkg, PrevEvent);
var lstExpResult = new List<string> {CountHrs.NormalCounter.ToString(),
CountHrs.SATCounter.ToString(),
CountHrs.SUNCounter.ToString()};
UpdateBooking(bookingSesid, lstExpResult);
Just assume i have the value like below in the counter
NormalCounter =4
SATCounter=10
SUNCounter=6
am trying to add in to string list and update the database.is that the right way to do ? or any other options i have please.
my update booking method is below to give clear idea.
public static bool UpdateBooking(string BookingSesid,List<string>HoursByRate)
{
SchedwinEntities db = new SchedwinEntities();
string value = string.Empty;
for (int i = 0; i < 5; i++)
{
string str = " ";
if (i < HoursByRate.Count())
{
str = HoursByRate[i];
value += str + ((char)13).ToString() + ((char)10).ToString();
}
}
var query =
from SEVTs in db.SEVTs
where
SEVTs.SESID.Trim() == BookingSesid//SESID
select SEVTs;
foreach (var SEVTs in query)
{
SEVTs.USER3 = value;//value
}
try
{
db.SaveChanges();
return true;
}
catch (UpdateException ex)
{
return false;
}
}
Rather than passing a list of strings that represent doubles, you should pass a list of key-value pairs, construct a parametersized statement from them, and use the list of key-value-pairs to bind parameter values, like this:
class SqlParamBinding {
string Name {get;set;}
object Value {get;set;}
}
var lstExpResult = new List<SqlParamBinding> {
new SqlParamBinding { Name = "NormalCounter", Value = CountHrs.NormalCounter}
, new SqlParamBinding { Name = "SATCounter", Value = CountHrs.SATCounter}
, new SqlParamBinding { Name = "SUNCounter", Value = CountHrs.SUNCounter}
};
UpdateBooking(bookingSesid, lstExpResult);
Now that lstExpResult separates names from values, your UpdateBooking code could format the SQL expression as
WHERE NormalCounter=#NormalCounter AND SATCounter=#SATCounter AND ...
and then bind #NormalCounter, #SATCounter, and #SUNCounter to the values passed in the lstExpResult list.
If it is going to list of Counter classes then have List instead of List. Looks like you might be having bunch of Counter objects that might be getting updated or sent to the database.
Counter c = new Counter();
c. NormalCounter = 4
c.SATCounter = 10
c.SunCounter = 10
List<Counter> listCounter = new List<Counter>
listCounter.Add(c);
Code is more maintainable and readable.
If you are sending one object at a time, then no need of list at all. You can pass in the counter object to your UpdateMethod and parse it while updating the database.

Categories

Resources