what I have right now are two listbox which are lstItem and lstQty and I want to save both value into single textfile.
lstItem | lstQty
Chicken | 3
Fish | 2
Lamb | 1
I want this value saved into textfile like this:
Chicken | 3
Fish | 2
Lamb | 1
Instead of:
Chicken
Fish
Lamb
3
2
1
These is my codes:
string receiptFile = #"D:\VisualStudio2012\SalesDetails.txt";
StreamWriter file2 = new StreamWriter(receiptFile, true);
List<string> totalSales = new List<string>();
foreach (object item in lboItem.Items)
{
totalSales.Add(item as string);
file2.WriteLine(item);
}
foreach (object item2 in lboQty.Items)
{
totalSales.Add(item2 as string);
file2.WriteLine(item2);
}
file2.Close();
I know why it shows in textfile like what i mentioned above. It happens because i have no idea how to make it like what i want. Thank you in advance to anyone that can solve this.
Well, instead of your two loops you need only one and during this one loop you just need to concatenate values from both listboxes and write them to file.
Something like this:
int itemsCount = Math.Min(lboItem.Items.Count, lboQty.Items.Count);
for (int i = 0; i < itemsCount; i++)
{
string item = "";
if (i < lboItem.Items.Count)
item = lboItem.Items[i].ToString();
item += " | ";
if (i < lboQty.Items.Count)
item += lboQty.Items[i].ToString();
totalSales.Add(item);
file2.WriteLine(item);
}
I'm not sure why do you need totalSales list here - but it's up to your logic.
Also note - there is check here for the situation when sizes of listboxes are not equal. If your listboxes sizes are guarantied to be equal - this check is redundant you can simplify this code snippet to
int itemsCount = lboItem.Items.Count;
for (int i = 0; i < itemsCount; i++)
{
string item = string.Format("{0} | {1}", lboItem.Items[i], lboQty.Items[i]);
totalSales.Add(item);
file2.WriteLine(item);
}
If both listboxes always have the same number of items, maybe this helps you:
string receiptFile = #"D:\VisualStudio2012\SalesDetails.txt";
StreamWriter file2 = new StreamWriter(receiptFile, true);
for(int i=0; i < lboItem.Items.Count; i++)
{
file2.WriteLine(string.Format("{0} | {1}", lboItem.Items[i].ToString(), lboQty.Items[i].ToString()));
}
file2.Close();
I didn't realize the purpose of totalSales. If you need it, you can add it inside the for loop.
Related
I have a problem with duplicates words in memory game.
I have a code (bellow) and what I want to duplicate labels and pass it (in random position every time when app is open) to bellow row e.g
Open app first time
| label1 | label2 | label3 | <= first row
| label3 | label2 | label1 | <= second row
Open app second time
| label1 | label2 | label3 | <= first row
| label1 | label3 | label2 | <= second row
private void AssingWordsToSquares()
{
Label label;
int randomNumber;
string path = $"{_currentPath}\\Resources\\Words.txt";
_loadWordsList = File.ReadAllLines(path).ToList();
for (int i = 0; i < tableLayoutPanel1.Controls.Count; i++)
{
if (tableLayoutPanel1.Controls[i] is Label)
{
label = (Label)tableLayoutPanel1.Controls[i];
}
else
continue;
randomNumber = random.Next(0, _loadWordsList.Count);
label.Text = _loadWordsList[randomNumber];
_loadWordsList.RemoveAt(randomNumber);
}
``
So, at the moment, the function you shared is doing 2 things.
1 is to find random words from a dictionary in a file
2 is to place the words in a random order on screen
So you have 2 random operations happening. Remember the golden rule which is 1 function should try and do just 1 thing. It should have just 1 purpose.
So, you could seperate out that functionality to make it clearer.
We could start by creating a function that will generate a random list of words from your dictionary file. Something like this:
List<string> GenerateRandomWords(int numWords)
{
var randomWordList = new List<string>();
var wordList = System.IO.File.ReadAllLines("RandomWords.txt").ToList();
for (int nLoopCnt = 0; nLoopCnt < numWords; nLoopCnt++)
{
var randomNumber = random.Next(0, wordList.Count);
randomWordList.Add(wordList[randomNumber]);
}
return randomWordList;
}
Now you have your random words extracted from the file we need to put them on the screen in a random order. So, we could create another function GenerateRandomPosOrder that takes a TableLayoutPanel and generates a list of columns in a random order. So, each time you run this function is could return 1,2,3 or 1,3,2 or 3,2,1.
private HashSet<int> GenerateRandomPosOrder(TableLayoutPanel table)
{
Thread.Sleep(500);
Random rnd = new Random();
var result = new HashSet<int>();
while (result.Count < table.ColumnCount)
{
var randomNumber = rnd.Next(0, table.ColumnCount);
result.Add(randomNumber);
}
return result;
}
Now we can put these 2 functions together in your AssignWordsToSquares like so.
private void AssignWordsToSquares(TableLayoutPanel table)
{
var wordList = GenerateRandomWords(table.ColumnCount);
// loop around every row in the table
for (int rowCount = 0; rowCount < table.RowCount; rowCount++)
{
// this could return 0,2,1 or 1,0,2 or 1,2,0
var order = GenerateRandomPosOrder(table);
int pos = 0;
foreach (var randomPosition in order)
{
var tableCell = (Label)table.GetControlFromPosition(column: randomPosition, row: rowCount);
tableCell.Text = wordList[pos++];
}
}
}
The above function first gets a list of random words from the dictionary, then for ever row of the TableLayoutPanel it puts the words in a random order.
I have a list view and a richtextbox.
This richtextbox has data like below. And I want to input the first 5 lines in one row and 5 columns like below.
richtextbox example and List view example
I have the below code so far
for ( int i = 0; i < richTextBox1.Lines.Count(); i++)
{
string[] arry = new string[5];
ListViewItem itms;
arry[0] = richTextBox1.Lines[i];
arry[1] = richTextBox1.Lines[i+1];
arry[2] = richTextBox1.Lines[i + 1];
arry[3] = richTextBox1.Lines[i+2];
arry[4] = richTextBox1.Lines[i+3];
itms = new ListViewItem(arry);
listView1.Items.Add(itms);
}
But it is not giving me the desired output, as it repeats itself over and over like seen here
Undesired Output
Kindy let me know where I am going wrong
Your for loop is going line by line, not by groups of 5 lines.
Change it to this:
for ( int i = 0; i < richTextBox1.Lines.Count(); i += 5)
Basically what I need to do is so:
File no.1:
1
2
4
5
51
21
File no.2:
31
21
4
What should be exported:
1
2
5
51
Basically only export the lines that do not exist in the second text.
My current attempt:
bool exists = false;
string[] lines1 = File.ReadAllLines("path1");
string[] lines2 = File.ReadAllLines("path2");
for (int i = 0; i < lines1.Length; i++)
{
for (int g = 0; g < lines2.Length; g++)
{
if (lines1[i] == lines2[g])
{
exists = true;
Console.WriteLine("Exists!");
break;
}
}
if (!exists)
{
Console.WriteLine(lines1[i]);
exists = false;
}
}
Console.WriteLine("End of file reached");
Console.ReadLine();
I feel like there is a proper function for me to use, although this is what i came up with, thanks for your help!
Based on your desired result you can use LINQ and Except extension method. Like this:
string[] result = lines1.Except(lines2).ToArray();
In general case, if file2 can contain duplicates which you want to preserve, I suggest using HashSet<string>:
HashSet<string> toSkip = new HashSet<string>(File.ReadLines(path1));
var toExport = File
.ReadLines(path2)
.Where(line => !toSkip.Contains(line));
//.ToArray(); // <- if you want to materialize the final result
// Test
foreach (var item in toExport)
Console.WriteLine(item);
How can I display a specific set of items in an array?
I want to print 25 items to screen from index 0 to 24 and another 25 starting from index 25, in that order.
I can display all items, but how can I display from a specific index in the array to another specific index?
Example: I have 100 items in my array.
And I want to show from 0 to 3 and from 4 to 7 and so on.
For Example: String of letters: A B C D E F G etc.
And I want to show only A B C. But when I do something it show next 3 in array.
Since im using B_items as object in an array. I wanna show only 0, 1, 2 in array and again form 3, 4, 5 and so on.
public class B_items
{
public string Name {get; set;}
public int Value { Get; set;}
}
B_items[,] items;
public Inventory(Backpack Bpack, int Columns, int Rows, int SlotWidth, int SlothHeight, Vector2 Pos)
{
items = new B_items[Columns, Rows];
pos = Pos;
slotWight = SlotWidth;
slotHeight = SlothHeight;
backpack = Bpack;
this.Columns = Columns;
this.Rows = Rows;
LoadItems(Bpack);
}
for(int i = 0; i < items.Length; i++)
{
Console.WritleLine(Items[i].Name;
}
}
if (items[X, Y] != null)
{
spriteBatch.Draw(items[X, Y].Texure, new Rectangle(DrawX, DrawY, slotWight, slotHeight),new Rectangle(0,0,64,64),Color.White);
if (items[X, Y].StackSize > 1)
{
spriteBatch.DrawString(AssetManager.GetInstance().font["Arial8"], items[X, Y].StackSize.ToString(), new Vector2(DrawX + 24, DrawY + 22), Color.White);
}
}
This will write all and I want to do 5 of those. While I have 100 and each time I press a button it shows next 5 in that list.
How can I show specific list of items...form index 0 to 10 and form 11 to 20 and so on.
var stats = items.Skip(5).Take(5)
I can't do this... I do not see .Take(param) or .Skip(param)
I am using
using System.Linq;
using System;
I'm sorry for not being specific. I can't nor sometimes know how to ask a valid question. My English is not my first language so fix my grammar and delete this line
And I want to show from 0 to 3 and from 4 to 7 and so on.
You can use a normal for-loop and specify the step size that you want to increment. Every step you would skip the items that you have already processed and take each time only the specified step size (in your case 3).
This should do the trick:
// test array
int[] array = Enumerable.Range(1, 100).ToArray();
int stepsize = 3;
for (int i = 0; i < array.Length; i += stepsize)
{
string s = String.Join(" ", array.Skip(i).Take(stepsize));
Console.WriteLine(s);
}
You can use LINQ to access ranges of your array. Skip lets you decide where you start your range and Take how many entries you want.
If you want D E F from your example you can use:
var subRange = items.Skip(3).Take(3);
foreach (string item in subRange) {
Console.WriteLine(item);
}
I'm very new to programming so apologies if this is a very obvious question. Ive searched online but not found an answer that quite fits yet.
I am writing a programme that interprets bytes from an index within a filestream. Once they have been converted into human readable dates/strings/ints etc I wanted to use a Winform to display the results in columns. Currently I using a listbox and just dispalying each entry seperated by columns but this feels lile a very clunky way of doing it.
Can someone please suggest how I might go about placing the results into a display that uses columns?
It's better to use a ListView than a ListBox in your case. Here's an example showing all words in a string in separate columns in a ListView:
Make sure following property is set to your ListView (here the Name is ColumnsListView):
ColumnsListView.View = View.Details;
This method takes a string, splits it by space and adds a column for each of the values:
private void SetListView(string input)
{
var values = input.Split(' ');
ColumnsListView.Columns.Add("Column1");
var item = new ListViewItem(values[0]);
for (var i = 1; i < values.Length; i++)
{
ColumnsListView.Columns.Add("Column" + (i+1));
item.SubItems.Add(new ListViewItem.ListViewSubItem { Text = values[i] });
}
ColumnsListView.Items.Add(item);
}
This can be done differently when using LinQ's Skip() method to add the item with subitems:
private void SetListView(string input)
{
var values = input.Split(' ');
for (var i = 0; i < values.Length; i++)
ColumnsListView.Columns.Add("Column" + (i + 1));
var item = new ListViewItem(values[0]);
item.SubItems.AddRange(values.Skip(1).ToArray());
ColumnsListView.Items.Add(item);
}
Update:
Here's an example in case you want to use a DataGridView:
private void SetDataGridView(string input)
{
var values = input.Split(' ');
for (var i = 0; i < values.Length; i++)
ColumnsDataGridView.Columns.Add("Column" + (i + 1), "Column" + (i + 1));
ColumnsDataGridView.Rows.Add(values);
}