Start a process with lists as argument? - c#

I would like to pass two string lists (one namd checkeds and one named remaining) as arguments to program but I can't figure out how. Thanks in advance for any help.
This is what I tried lastly :
static void Main(List<string> args)
{
List<string> checkeds = new List<string>();
List<string> remaining = new List<string>();
int listCount = 0;
foreach(List<string> list in args)
{
listCount++;
if (listCount == 1)
foreach (string item in list)
checkeds.Add(item);
else if (listCount == 2)
foreach (string item in list)
remaining.Add(item);
}
}

The parameter to Main to receive command line arguments is always string[]. You can't use List<string> instead.
I'd suggest that if you want two lists of strings, you just have each list as a single command line argument, separated by commas:
using System;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
if (args.Length != 2)
{
Console.WriteLine("Required arguments: <list of checked> <list of remaining>");
return;
}
var checkedList = new List<string>(args[0].Split(','));
var remainingList = new List<string>(args[1].Split(','));
Console.WriteLine("Checked items:");
foreach (var item in checkedList)
{
Console.WriteLine($" {item}");
}
Console.WriteLine("Remaining items:");
foreach (var item in remainingList)
{
Console.WriteLine($" {item}");
}
}
}
Then if you run it like this:
Program.exe a,b,c d,e,f,g
You'll get output of:
Checked items:
a
b
c
Remaining items:
d
e
f
g

I would suggest passing a comma separated(or some other delimiter) and then split them in the Main method like this
List<string> checkeds = args[0].Split(',').ToList();
List<string> remaining = args[1].Split(',').ToList();
-- Futher processing ...
You need to pass values to your app like
AppName a,b,c,d e,f,g,h

Related

Formatting values from a list

Before getting into C# I used to study Python. I did this small project where the program makes a list and whatever you type it is added to the list. I tried to do the same in C# as a form of practice, but I seem to be doing something, if not everything, for the program won't work. This is my code:
using System;
using System.Collections.Generic:
class idk
{
static void Main(string[] args)
{
List<string> list = new List<string>();
for ( ; true; )
{
Console.Write("Tell me something: ");
var inp = Console.ReadLine();
list.Add(inp);
var i = 1;
foreach (string a in list)
var ni = i + 1;
Console.WriteLine(String.Format("{0}. {1}", ni, a));
}
}
}
So I want my program to take the input, save it in the list, and then print the list but in the form of (e.g.)
Idk
C
A
Like an actual list, where you number each item and all that. So I tried to do the same I did in Python:
List = []
while True:
item = input("Tell me something: ")
List.append(item)
i = 1
for val in List:
print(f"{i}. {val}")
i += 1
Is there something I can edit from my code to make it do the same? Or perhaps I may need to rewrite the whole thing? Thanks for your help.
I suggest loop type changing from foreach to for:
for (int i = 0; i < list.Count; ++i)
Console.WriteLine($"{i + 1}. {list[i]}");
If you insist on foreach:
int index = 0;
foreach (var item in list)
Console.WriteLine($"{++index}. {item}");
You can print the list in one go with a help of Join (to join list's items) and Linq (to query the list):
Console.WriteLine(string.Join(Environment.NewLine, list
.Select((value, index) => $"{index + 1}. {value}")));
I think you should only print the contents of the list at the end when the user has decided they don't want to enter anything anymore:
using System;
using System.Collections.Generic;
class MainClass {
public static void Main (string[] args) {
List<string> strList = new List<string>();
while (true) {
Console.Write("Tell me something: ");
var str = Console.ReadLine();
if (String.IsNullOrWhiteSpace(str)) {
break;
}
strList.Add(str);
}
for (var i = 0; i < strList.Count; i++) {
Console.WriteLine(String.Format("{0}. {1}", i + 1, strList[i]));
}
}
}
Example Usage:
Tell me something: idk
Tell me something: C
Tell me something: A
Tell me something:
1. idk
2. C
3. A
Try it here.

Check if List<string> exists

This is my code
List<string> list = new List<string>() { "bfd", "jy", "aaaaa", "ndnk", "ntfn", "gfm", "gfm", "mhgd5h", "srsr", "ntr", "mtmyt", "dmy", "mmy6", "ngn9d", "y6m1", "d8dm", "bbbbb", "tym", "dmj", "trsh", "tsr"};
List<string> test = new List<string>() {"aaaaa","bbbbb","ccccc","ddddd","eeeee","fffff","ggggg" };
foreach (var a in list)
{
foreach (var i in test)
{
if (i.StartsWith(a) == false)
{
Console.WriteLine(i);
}
}
}
I want to output from the list and match in the test. If the test exists, then it will not be displayed. If there is no side output,But there may be a problem with my code, it will output the same value many times
The list contains aaaaa, according to logic, aaaaa should not be output
Try this:
List<string> list = new List<string>(){"bfd", "jy", "aaaaa", "ndnk", "ntfn", "gfm", "gfm", "mhgd5h", "srsr", "ntr", "mtmyt", "dmy", "mmy6", "ngn9d", "y6m1", "d8dm", "bbbbb", "tym", "dmj", "trsh", "tsr"};
List<string> test = new List<string>(){"aaaaa", "bbbbb", "ccccc", "ddddd", "eeeee", "fffff", "ggggg"};
foreach (var a in list)
{
if (!test.Contains(a))
{
Console.WriteLine(a);
}
}
There are simple solutions using LINQ. But since I assume this is an exercise, I will show you the detailed version using loops.
The problem is that the WriteLine is inside the inner loop. Therefore you will get many repetitions. Store the outcome of the test in a Boolean variable and place the display part after the inner loop.
foreach (var a in list)
{
bool found = false;
foreach (var i in test)
{
if (i.StartsWith(a))
{
found = true;
break; // Exit the inner loop
}
}
if (!found)
{
Console.WriteLine(a); // We must output a here since i out of scope.
}
}
Also, if you want to know whether a specific string is contained in the list, you should probably replace i.StartsWith(a) with i == a.
The code becomes easier to read, if you extract the list search into its own method
private bool IsInList(List<string> list, string item)
{
foreach (string s in list)
{
if (s == item)
{
return true;
}
}
return false;
}
Now, you don't need the Boolean variable any more
foreach (var a in list)
{
if (!IsInList(test, a))
{
Console.WriteLine(a);
}
}
I used !condition (pronounce: "not condition") instead of condition == false. It's terser.
I assume that this is an exercise. In production code you would simply use the built in method Contains of the list.
foreach (var a in list)
{
if (!test.Contains(a))
{
Console.WriteLine(a);
}
}
or even (as #mjwills suggests in his comment):
foreach (var a in list.Except(test)) {
Console.WriteLine(a);
}

how to remove duplicate data for group query in Linq

I'm trying to find a distinct list of filenames related to each bugid, and I used linq to group all filenames related to each bug id. I don't know how I can remove duplicate filenames related to each bugid,in file ouput I have multiple rows like this:
bugid filename1 filename2 filename3 filename4 .............
there are multiple rows with the same bugid and also there duplicate filenames for each bug id,
this is my code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
namespace finalgroupquery
{
class MainClass
{
public static void Main (string[] args)
{
List <bug> list2=new List <bug> ();
using(System.IO.StreamReader reader1= new System.IO.StreamReader( #"/home/output"))
using (System.IO.StreamWriter file = new System.IO.StreamWriter( #"/home/output1"))
{string line1;
while ((line1=reader1.ReadLine())!=null)
{ string[] items1=line1.Split('\t');
bug bg=new bug();
bg.bugid=items1[0];
for (int i=1; i<=items1.Length -1;i++)
{ bg.list1.Add(items1[i]);}
list2.Add(bg);
}
var bugquery= from c in list2 group c by c.bugid into x select
new Container { BugID = x.Key, Grouped = x };
foreach (Container con in bugquery)
{
StringBuilder files = new StringBuilder();
files.Append(con.BugID);
files.Append("\t");
foreach(var x in con.Grouped)
{
files.Append(string.Join("\t", x.list1.ToArray()));
}
file.WriteLine(files.ToString()); }
}
}
}
public class Container
{
public string BugID {get;set;}
public IGrouping<string, bug> Grouped {get;set;}
}
public class bug
{
public List<string> list1{get; set;}
public string bugid{get; set;}
public bug()
{
list1=new List<string>();
}
}
}
}
From your description it sounds like you want to do this:
List <bug> bugs = new List<bug>();
var lines = System.IO.File.ReadLines(#"/home/bugs");
foreach (var line in lines) {
string[] items = line.Split('\t');
bug bg=new bug();
bg.bugid = items[0];
bg.list1 = items.Skip(1).OrderBy(f => f).Distinct().ToList();
bugs.Add(bg);
}
This will produce a list of objects, where each object has a unique list of filenames.
Try to use this code :
var bugquery = from c in list2
group c by c.bugid into x
select new bug { bugid = x.Key, list1 = x.SelectMany(l => l.list1).Distinct().ToList() };
foreach (bug bug in bugquery)
{
StringBuilder files = new StringBuilder();
files.Append(bug.bugid);
files.Append("\t");
files.Append(string.Join("\t", bug.list1.ToArray()));
file.WriteLine(files.ToString());
}
Thanks to the combination of SelectMany and Distinct Linq operators, you can flatten the filename list and delete duplicates in a single line.
SelectMany (from msdn):
Projects each element of a sequence to an IEnumerable and flattens
the resulting sequences into one sequence.
Distinct (from msdn):
Returns distinct elements from a sequence.
It also means that your Container class is no longer needed as there's no need to iterate through the IGrouping<string, bug> collection anymore (here list1 contains all the bug related filenames without duplicates).
Edit
As you may have some blank lines and/or empty strings after reading and parsing your file, you could use this code to get rid of them :
using (System.IO.StreamReader reader1 = new System.IO.StreamReader(#"/home/sunshine40270/mine/projects/interaction2/fasil-data/common history/outputpure"))
{
string line1;
while ((line1 = reader1.ReadLine()) != null)
{
if (!string.IsNullOrWhiteSpace(line1))
{
string[] items1 = line1.Split(new [] { '\t' }, StringSplitOptions.RemoveEmptyEntries);
bug bg = new bug();
bg.bugid = items1[0];
for (int i = 1; i <= items1.Length - 1; i++)
{
bg.list1.Add(items1[i]);
}
list2.Add(bg);
}
}
}
You'll notice :
New lines stored in line1 are checked for emptyness as soon as they are retrieved from your stream (with !string.IsNullOrWhiteSpace(line1))
To omit empty substrings from the return value of the string.Split method, you can use the StringSplitOptions.RemoveEmptyEntries parameter.
Hope this helps.

How to skip a specific position within a for each loop in c sharp?

List<string> liste = new List<String>
{
"A","B","C","D"
};
foreach (var item in liste)
{
System.Diagnostics.Debug.WriteLine(item.ToString());
}
for (int i = 0; i < liste.Count; i++)
{
if (i == 0)
continue;
System.Diagnostics.Debug.WriteLine(liste[i].ToString());
}
How do i skip a specific position in a foreach loop? I do not want to evaluate any values, but just skip the position x.
It has to be a specific position. One could choose position 0 or maybe position 7.
It is very easy to skip the first item in the list:
foreach(var item in list.Skip(1))
{
System.Diagnostics.Debug.WriteLine(item.ToString());
}
If you want to skip any other element at index n, you could write this:
foreach(var item in list.Where((a,b) => b != n))
{
System.Diagnostics.Debug.WriteLine(item.ToString());
}
In this example I use a lambda expression that takes two arguments: a and b. Argument a is the item itself, while argument b is the index of the item.
The relevant pages on MSDN that describe these extension methods are:
IEnumerable.Skip()
IEnumerable.Where()
You could even write your own extension method that allows you to skip an element in a list:
public static class MyEnumerableExtensions
{
public static IEnumerable<T> SkipAt<T>(this IEnumerable<T> list, int index)
{
var i = 0;
foreach(var item in list)
{
if(i != index)
yield return item;
i++;
}
}
}
This will allow you to write something like this to skip an item:
foreach(var item in list.SkipAt(2))
{
System.Diagnostics.Debug.WriteLine(item.ToString());
}
A foreach loop iterates over a collection that implements IEnumerable. The enumerator exposes the current item and a method to move onto the next item - it has no concept of an index.
You could always do:
var i = 0;
foreach (var item in liste) {
if (i++ == skip) continue;
Debug.WriteLine(item.ToString());
}
But this seems unnecessarily contrived. If you need an index, go with a for loop.
The other option is to remove the undesired item from the List before iterating:
foreach (var item in liste.Take(n-1).Union(liste.Skip(n))) {
Debug.WriteLine(item.ToString());
}
I love list's .ForEach, here's my take using #Elian's .SkipAt(n) and .ForEach:
var list = new List<String> { "A", "B", "C", "D" };
list = list.SkipAt(1).ToList();
list.ForEach(Debug.WriteLine);
You should try using the enhanced version of the Where extension method that allows you to filter on item and index.
Check the reference.
http://msdn.microsoft.com/en-us/library/bb549418.aspx
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Verbatim list");
List<string> list = new List<String> { "A","B","C","D" };
foreach (var item in list)
{
Console.WriteLine(item.ToString());
}
Console.WriteLine("Filtered list");
int itemToSkip = 2;
foreach (var item in list.Where((item, index) => index != itemToSkip))
{
Console.WriteLine(item.ToString());
}
Console.ReadKey();
}
}
}
This will give you the following output.
Verbatim list
A
B
C
D
Filtered list
A
B
D
To skip a position inside the foreach loop, one option is that you can skip the action inside the foreach loop by using an if statement, like
foreach(var item in liste)
{
if (item != 'X')
{
//do something
}
}
But i am waiting for better solutions

Check if collection is empty or not

public ActionResult Create(FormCollection collection, FormCollection formValue)
{
try
{
Project project = new Project();
TryUpdateModel(project, _updateableFields);
var devices = collection["devices"];
string[] arr1 = ((string)devices).Split(',');
int[] arr2 = Array.ConvertAll(arr1, s => int.Parse(s));
project.User = SessionVariables.AuthenticatedUser;
var time = formValue["Date"];
project.Date = time;
project.SaveAndFlush();
foreach (int i in arr2)
{
Device d = Device.Find(i);
d.Projects.Add(project);
d.SaveAndFlush();
}
return RedirectToAction("Index");
}
catch (Exception e)
{
return View(e);
}
}
I want to wrap the foreach in a if statement which checks if
var devices = collection["devices"];
is empty or not. If its empty the for each should not be executed. For the record, collection["devices"] is a collection of checkbox values from a form.
You can use the Count field to check if the collection is empty or not
so you will end up with something like this :
if(devices.Count > 0)
{
//foreach loop
}
You can use the method Any to know if a collection as any element.
if (devices.Any())
{
//devices is not empty
}
You do not need to check if the collection is empty, if it is empty the code inside the ForEach will not be executed, see my example below.
using System;
using System.Collections.Generic;
namespace Test
{
class Program
{
static void Main(string[] args)
{
List<string> emptyList = new List<string>();
foreach (string item in emptyList)
{
Console.WriteLine("This will not be printed");
}
List<string> list = new List<string>();
list.Add("item 1");
list.Add("item 2");
foreach (string item in list)
{
Console.WriteLine(item);
}
Console.ReadLine();
}
}
}
Your code, as it stands, won't work, as you say that collection["devices"] is a collection of checkbox values, and yet you're casting it to a string. Do you mean collection is the checkbox values? What is the exact type of collection?
Any object that implements ICollection or ICollection<T> can be checked whether it's empty or not by checking if the Count property is greater than zero.
How about checking the array length
if (arr2.length > 0)
{
foreach (int i in arr2)
{
Device d = Device.Find(i);
d.Projects.Add(project);
d.SaveAndFlush();
}
}
This worked for me in Dot Net Core but only for IEnumerable of Models not Entities
(I got a bit of help from AutoMapper)
Cast it as a List then check the Capacity
IEnumerable<vwPOD_Master> podMasters = _podRepository.GetNewPods(PartNumber);
IEnumerable<NewPODsDTO> podList = Mapper.Map<IEnumerable<NewPODsDTO>>(podMasters);
if (((List<NewPODsDTO>)podList).Capacity == 0) {
return NotFound();
}

Categories