How to join same lines in textbox and count them - c#

Hey Guys I have Problem I have a textbox who will have sometimes same lines now I need to count them and show the number in joined line with the text
private void textBox1_TextChanged(object sender, EventArgs e)
{
string[] same =textBox1.Text.Split(new string[] { Environment.NewLine }, StringSplitOptions.None).Distinct().ToArray();
textBox1.Text = string.Join("\r\n", same);
}
in this code it will join the lines and I am able to see just one line but I need a count of lines and if I have some number in that line to count that also
for example:
Earth 2
Water
Air
Earth
Expected :
Earth x2 4
Water
Air

Your question is a bit confusing, BTW I solve it this way.
First I made a class for each result item
Result Class
public class Result
{
public string Item{ get; set; }
public int Count{ get; set; }
public int Value{ get; set; }
}
Then I have a button to translate the 'user input' to the desired format
You can run this method as textbox1_changed
Button Translate Clicked Method
private void btnTranslate_Click(object sender, EventArgs e)
{
var items = textBox1.Text.Split(new string[] { Environment.NewLine }, StringSplitOptions.None).ToList();
var results = new List<Result>();
foreach (var item in items)
{
var text = item;
var value = 0;
var row = item.Split(' ').ToList();
if (row.Count == 2) // item contains value like: Earth 2
{
text = row[0];
Int32.TryParse(row[1], out value);
}
var result = results.FirstOrDefault(r => r.Item.Equals(text));
if (result == null) // first time item apears in the list
{
result = new Result
{
Item = text,
Count = 1,
Value = value
};
results.Add(result);
}
else // item added before should increase the count
{
result.Count++;
result.Value += value;
}
}
textBox2.Text = Prettify(results); // lets make the result pretty
}
In the end I declared Prettify function to make the result as you wanted
Prettify Method
public string Prettify(List<Result> results)
{
var prettify = "";
int row = 0;
foreach (var result in results)
{
prettify += $"{++row}. {result.Item}"; // 1. Earth
if (result.Count > 1)
prettify += $" x{result.Count}"; // 1. Earth x2
if (result.Value > 0)
prettify += $" {result.Value}"; // 1. Earth x2 4
prettify += Environment.NewLine;
}
return prettify;
}
Here is the output
Output
I guess the core is right, you could customize it
Have fun

Related

C# Multiplying the values of an array together which are loaded from a textfile into a List<>

So I have an array, strArray, that stores the values of my text files which has 3 columns. I think this is called a two or three dimensional array, not sure. Or maybe one dimensional. I have a List<> called Inventory which adds the data to it.
I currently have three successful columns I just need the fourth. The fourth column is the second and third column multiplied together, which is a total price. The second column is an int, "Number of Items", the third is a decimal, "Price" and the fourth is a decimal, "Total Price" which is Number of Items * Price.
I'll go ahead and post my code, I am also using four list boxes for the data. Three columns (or three list boxes) work fine, but I just gotta get the fourth one figured out.
Sorry for the large amount of code, I figured if I copied all of it it'll make it easier to see if an error occurred earlier on. btnLoadInfo_Click is the event/method where the main issue is.
namespace TCSCapstone
{
public partial class frmInventory : Form
{
List<frmInventory> Inventory = new List<frmInventory>();
public frmInventory()
{
InitializeComponent();
}
public string ItemName { get; set; }
public int NumberOfItems { get; set; }
public decimal Price { get; set; }
public decimal TotalPrice { get; set; }
string selectedList = "";
private void cmbList_SelectedIndexChanged(object sender, EventArgs e)
{
selectedList = this.cmbList.GetItemText(this.cmbList.SelectedItem);
lstItemName.DataSource = null;
lstNumberOfItems.DataSource = null;
lstPrice.DataSource = null;
lstItemName.Items.Clear();
lstNumberOfItems.Items.Clear();
lstPrice.Items.Clear();
lstTotalPrices.Items.Clear();
if (selectedList == "Creative Construction")//if the selected combo box item equals the exact string selected
{
selectedList = "creative"; //then the string equals creative, which is creative.txt but I add the .txt in the btnLoadInfo method
} else if (selectedList == "Paradise Building")
{
selectedList = "paradise";//this is for paradise.txt
}
else if (selectedList == "Sitler Construction")
{
selectedList = "sitler";//this is for sitler.txt
}
else
{
MessageBox.Show("Please select one of the items.");
}
}`
private void btnLoadInfo_Click(object sender, EventArgs e)
{
Inventory.Clear(); //Clears the entire Inventory List
using (StreamReader invReader = new StreamReader(selectedList +
".txt"))
{
while (invReader.Peek() >= 0)
{
string str;
string[] strArray;
str = invReader.ReadLine();
strArray = str.Split(',');
frmInventory currentItem = new frmInventory();
currentItem.ItemName = strArray[0];
currentItem.NumberOfItems = int.Parse(strArray[1]);
currentItem.Price =
decimal.Parse(strArray[2]);
strArray[1].
currentItem.TotalPrice = decimal.Parse(strArray[1] *
strArray[2]);
Inventory.Add(currentItem);
}
}
displayLists(); //Calls the displayLists method to update list
//boxes at the end of the button click event
}//end of btnLoadInfo
void displayLists()
{
//Resets the listboxes datasources by setting them to null
lstItemName.DataSource = null;
lstNumberOfItems.DataSource = null;
lstPrice.DataSource = null;
lstItemName.Items.Clear();
lstNumberOfItems.Items.Clear();
lstPrice.Items.Clear();
lstTotalPrices.Items.Clear();
lstItemName.DisplayMember = "ItemName";
lstItemName.ValueMember = "";
lstItemName.DataSource = Inventory;
lstNumberOfItems.DisplayMember = "NumberOfItems";
lstNumberOfItems.ValueMember = "";
lstNumberOfItems.DataSource = Inventory;
lstPrice.DisplayMember = "Price";
lstPrice.ValueMember = "";
lstPrice.DataSource = Inventory;
}
Your TotalPrice property should be a mathematical equation, not something you set independently of the number of items and their prices.
Change the property to this:
public decimal TotalPrice{
get{ return NumberOfItems * Price; }
}
Delete the line that sets TotalPrice in your loop; it's no longer necessary because you've set the item price and the number of items; the total price inherently follows from these
You're trying to multiply two strings together. Instead, multiply the numeric values that you have already parsed:
currentItem.TotalPrice = currentItem.NumberOfItems * currentItem.Price;

How can I make 1 button click fill out 2 different text boxes

I need help making this program fill out 2 different text boxes. It works if I only use it to fill out 1 text box using a First name. But when I try and add another text box to generate a random Last name it just seems to do fail.
private void button1_Click(object sender, EventArgs e)
{
Random r = new Random();
int currentLine = 1;
string pick = null;
foreach (string line in File.ReadLines("C:\\First Names.txt"))
{
if (r.Next(currentLine) == 0)
{
pick = line;
}
++currentLine;
textBox1.Text = pick;
}
Random n = new Random();
int currentLine1 = 1;
string pick1 = null;
foreach (string line1 in File.ReadLines("C:\\Last Names.txt"))
{
if (n.Next(currentLine1) == 0)
{
pick1 = line1;
}
++currentLine1;
textBox2.Text = pick1;
}
}
}
}
Check whether the path for the file is appropriate.
You need not create two objects for the same class and access them differently.One object is enough.
3.Check whether data is there in the file or not.`Random r = new Random();
int currentLine = 1;
string pick = null;
foreach (string line in File.ReadLines("C:\\First Names.txt"))
{
if (r.Next(currentLine) == 0)
{
pick = line;
}
++currentLine;
textBox1.Text = pick;
}
currentLine=0;pick=0;
foreach (string line in File.ReadLines("C:\\Last Names.txt"))
{
if (r.Next(currentLine) == 0)
{
pick = line;
}
++currentLine;
textBox2.Text = pick;
}
}`
If the first iteration gets the value, then the second must also get. Else there is some problem with Text file or the 'textBox2' is not the correct ID you are looking for.

Need help appending a variable in listbox

When the Add button is pressed the price is taken from the second half of a 'split' line in the first list box. This is then multiplied by a value entered in a textbox or just entered as is into the second listbox.
I have then added a line below it in the second list box with the total price. When a new item is added the code removes the previous total price and replaces it with the new updated total price.
I'm looking to then append (add all the prices being listed in the second listbox) the prices together in the 'total price' section of the last line of the second list box.
Below is the code I have written so far.
private void button1_Click(object sender, EventArgs e)
{
string TheItem = Convert.ToString(listBox1.SelectedItem);
string[] theSplits = TheItem.Split(' ');
string FirstSplit = theSplits[0];
string SecondSplit = theSplits[1];
Decimal theNewTotal;
Decimal theValue;
if (textBox1.Text == "")
{
listBox2.Items.Add(TheItem);
listBox2.Items.Add("Total Price:" + SecondSplit);
}
else
{
theValue = Convert.ToDecimal(SecondSplit) * Convert.ToDecimal(textBox1.Text);
listBox2.Items.Add(textBox1.Text + "x " + TheItem);
theNewTotal = theValue;
listBox2.Items.Add("Total Price:" + theNewTotal);
}
if (listBox2.Items.Count > 2)
{
int theNumber = listBox2.Items.Count;
listBox2.Items.RemoveAt(theNumber-3);
}
}
You'd be better off starting by removing the total price first, as you expend some effort trying to work around that. So something like:
private void button1_Click(object sender, EventArgs e) {
RemoveLastTotal();
AppendPrices();
AppendTotal();
}
private void RemoveLastTotal() {
var lastItemIndex = listBox2.Items.Count-1;
if (listBox2.Items[lastItemIndex].StartsWith("Total Price:"))
{
listBox2.Items.RemoveAt(lastItemIndex);
}
}
private void AppendPrices() {
string TheItem = Convert.ToString(listBox1.SelectedItem);
string[] theSplits = TheItem.Split(' ');
string itemDesc = theSplits[0];
string itemPrice = theSplits[1];
float quantity = (string.IsNullOrEmpty(textBox1.Text))? 0: float.Parse(textBox1.Text)
if (quantity==0) {
listBox2.Items.Add(TheItem);
} else {
var lineTotal = Convert.ToDecimal(itemPrice) * quantity;
listBox2.Items.Add(textBox1.Text + " x " + TheItem + " = " + lineTotal);
}
}
private void AppendTotal()
{
var total = 0;
foreach(var item in listBox2.Items)
{
var splits = item.Split(' ');
total += decimal.parse(splits[splits.length-1]);
}
listBox2.Items.Add("Total Price:" + total);
}
That said, if you really want to do it "properly", you should separate the view i.e. the listbox from the model (DataTable for instance).

get coordinates from wcf service

I managed to get my wcf service from http://kailun92wcf.cloudapp.net/Service1.svc, however I need help to consume it and get the xCoord and yCoord to plot it in my map. I managed to get the name but I am stuck at calling out the xCoord and yCoord from wcf service.
private void polyc_Checked(object sender, RoutedEventArgs e)
{
var service = new Service1Client();
service.getRecommendPlaceAsync(new getRecommendPlaceRequest { activityId = 2 });
service.getRecommendPlaceCompleted += new EventHandler<MyCloudService.getRecommendPlaceCompletedEventArgs>(RecommendedPlaceRequestComplete);
}
void RecommendedPlaceRequestComplete(object sender, MyCloudService.getRecommendPlaceCompletedEventArgs e)
{
if (e.Error == null)
{
var result = String.Join(",", (from place in e.Result.getRecommendPlaceResult select place.Name).ToArray());
MessageBox.Show(result);
}
else
{
MessageBox.Show("An error occured: " + e.Error.Message);
}
GraphicsLayer graphicsLayer = map.Layers["polyCoords"] as GraphicsLayer;
foreach (Classes.Places location in data)
{
MapPoint point = new MapPoint(Convert.ToDouble(location.XCoord), Convert.ToDouble(location.YCoord));
mcp.Add(location);
ESRI.ArcGIS.Client.Graphic graphic = new ESRI.ArcGIS.Client.Graphic() { Geometry = point, Symbol = PolyMarkerSymbol };
graphicsLayer.Graphics.Add(graphic);
}
}
You can get a list of coordinates from the same set of results that you are retrieving your place names from
instead of
var result = String.Join(",", (from place in e.Result.getRecommendPlaceResult select place.Name).ToArray());
Create a class structure such as
public class Points
{
public decimal XCoordinate { get; set; }
public decimal YCoordinate { get; set; }
}
then have
var coordinates = from place in e.Result.getRecommendPlaceResult select new Points {XCoordinate = place.XCoord, YCoordinate = place.YCoord};
coordinates should now have your list.
You are probably just better of having a list of places such as
var places = from place in e.Result.getRecommendPlaceResult select place;
then you can get any property from the elements in the list
foreach (var place in places)
{
MessageBox.Show(string.Format("Place: {0} at {1}, {2}", place.Name, place.XCoord, place.YCoord));
}

Only top row of DataGridView updating?

I have a DataGridView that I'm populating from a list. The function that edits this list is called LoadCollectionData()'. Extra rows get added to the list just fine, and the relevant data pertaining to that row populates when the row is added.
The problem is that later on when other data is being changed that'd alter what's displayed on the datagrid, only the top row continues to update, all of the others remain the same.
Here's the code for the method:
public bool haschanged = false;
public class KeywordDensity
{
public bool included { get; set; }
public string keyword { get; set; }
public string occurences { get; set; }
public string density { get; set; }
}
public int WordCount(string txtToCount)
{
string pattern = "\\w+";
Regex regex = new Regex(pattern);
int CountedWords = regex.Matches(txtToCount).Count;
return CountedWords;
}
public int KeywordCount(string txtToCount, string pattern)
{
Regex regex = new Regex(pattern);
int CountedWords = regex.Matches(txtToCount).Count;
return CountedWords;
}
public List<KeywordDensity> LoadCollectionData()
{
string thearticle = txtArticle.Text.ToLower();
string keywordslower = txtKeywords.Text.ToLower();
string[] keywordsarray = keywordslower.Split('\r');
List<KeywordDensity> lsikeywords = new List<KeywordDensity>();
bool isincluded = false;
double keywordcount = 0;
double wordcount = WordCount(thearticle);
double thedensity = 0;
foreach (string s in keywordsarray)
{
if (s != "")
{
keywordcount = KeywordCount(thearticle, s);
thedensity = keywordcount / wordcount;
thedensity = Math.Round(thedensity, 4) * 100;
if (thearticle.Contains(s))
{
isincluded = true;
}
else
{
isincluded = false;
}
lsikeywords.Add(new KeywordDensity()
{
included = isincluded,
keyword = s,
occurences = keywordcount.ToString(),
density = thedensity.ToString() + "%"
});
}
}
return lsikeywords;
}
private void txtArticle_TextChanged(object sender, EventArgs e)
{
if (haschanged == false)
haschanged = true;
lblWordCountNum.Text = WordCount(txtArticle.Text).ToString();
dataGrid.DataSource = LoadCollectionData();
}
private void dataGrid_MouseUp(object sender, MouseEventArgs e)
{
int cursorpos = 0;
string copied = "";
if (dataGrid.CurrentCellAddress.X == 1) //Only grab content if the "Keyword" column has been clicked on
copied = " " + dataGrid.CurrentCell.Value.ToString() + " ";
cursorpos = txtArticle.SelectionStart;
txtArticle.Text = txtArticle.Text.Insert(cursorpos, copied);
}
What's even more odd, is that when I click on any of the rows, then they immediately update. However, unless the row is clicked on (unless it's the top one) it doesn't update.
Because of this, I suspect there may be some property I need to set on the dataGrid itself, or I need to somehow tell each row to refresh through code.
What's the dealio?
EDIT: It appears that the only reason that the cell that's clicked on updates is because I actively grab content from the cell. I commented out the code below and it stopped updating even when clicked on. It then would only update the top row's values and that's it.
Code:
//Moved above in EDIT 3
EDIT 2: Here's the class declaration for KeywordDensity:
//Moved above in EDIT 3
EDIT 3: Posted whole schebang.
I modified the code slightly, try this code.
string[] keywordsarray = keywordslower.Split
(new char[] {'\r','\n' }, StringSplitOptions.RemoveEmptyEntries);
You may need to Invalidate() the control to trigger a repaint.
call the DataBind() method of the datagrid. That should do.
Update
There's a ResetBindings() in that case.

Categories

Resources