Using lambda expression to check filepath is valid c# - c#

I am trying to check whether a file path is valid using the following code
foreach (int i in UniqueRandom(0, 4))
{
var wbImage = getCharBitmap(c, rndFolder, i);
}
The UniqueRandom method generates non repeating random numbers between 0 to 4. Each number i represents a file name, which may or may not exist. If the file exist, the getCharBitmap method will return a WritableBitmap object, otherwise, it will return null.
I want to integrate a lambda expression to check whether the method returns null or not, then, if it's not null, I want to remember the i value and exit the foreach loop right away.
How to do this efficiently with the least amount of code?

Try
var firstExisting = UniqueRandom(0, 4)
.Select(i => new
{
Bitmap = GetCharBitmap(c, rndFolder, i),
Number = i
})
.FirstOrDefault(x => x.Bitmap != null);
if (firstExisting != null)
{
int j = firstExisting.Number;
}
Or the same without LINQ:
private static int FirstExisting()
{
foreach (int i in UniqueRandom(0, 4))
{
var wbImage = GetCharBitmap(c, rndFolder, i);
if (wbImage != null)
{
return i;
}
}
throw new Exception("No existing found"); // or return say -1
}

Related

How to find the placement of a List within another List?

I am working with two lists. The first contains a large sequence of strings. The second contains a smaller list of strings. I need to find where the second list exists in the first list.
I worked with enumeration, and due to the large size of the data, this is very slow, I was hoping for a faster way.
List<string> first = new List<string>() { "AAA","BBB","CCC","DDD","EEE","FFF" };
List<string> second = new List<string>() { "CCC","DDD","EEE" };
int x = SomeMagic(first,second);
And I would need x to = 2.
Ok, here is my variant with old-good-for-each-loop:
private int SomeMagic(IEnumerable<string> source, IEnumerable<string> target)
{
/* Some obvious checks for `source` and `target` lenght / nullity are ommited */
// searched pattern
var pattern = target.ToArray();
// candidates in form `candidate index` -> `checked length`
var candidates = new Dictionary<int, int>();
// iteration index
var index = 0;
// so, lets the magic begin
foreach (var value in source)
{
// check candidates
foreach (var candidate in candidates.Keys.ToArray()) // <- we are going to change this collection
{
var checkedLength = candidates[candidate];
if (value == pattern[checkedLength]) // <- here `checkedLength` is used in sense `nextPositionToCheck`
{
// candidate has match next value
checkedLength += 1;
// check if we are done here
if (checkedLength == pattern.Length) return candidate; // <- exit point
candidates[candidate] = checkedLength;
}
else
// candidate has failed
candidates.Remove(candidate);
}
// check for new candidate
if (value == pattern[0])
candidates.Add(index, 1);
index++;
}
// we did everything we could
return -1;
}
We use dictionary of candidates to handle situations like:
var first = new List<string> { "AAA","BBB","CCC","CCC","CCC","CCC","EEE","FFF" };
var second = new List<string> { "CCC","CCC","CCC","EEE" };
If you are willing to use MoreLinq then consider using Window:
var windows = first.Window(second.Count);
var result = windows
.Select((subset, index) => new { subset, index = (int?)index })
.Where(z => Enumerable.SequenceEqual(second, z.subset))
.Select(z => z.index)
.FirstOrDefault();
Console.WriteLine(result);
Console.ReadLine();
Window will allow you to look at 'slices' of the data in chunks (based on the length of your second list). Then SequenceEqual can be used to see if the slice is equal to second. If it is, the index can be returned. If it doesn't find a match, null will be returned.
Implemented SomeMagic method as below, this will return -1 if no match found, else it will return the index of start element in first list.
private int SomeMagic(List<string> first, List<string> second)
{
if (first.Count < second.Count)
{
return -1;
}
for (int i = 0; i <= first.Count - second.Count; i++)
{
List<string> partialFirst = first.GetRange(i, second.Count);
if (Enumerable.SequenceEqual(partialFirst, second))
return i;
}
return -1;
}
you can use intersect extension method using the namepace System.Linq
var CommonList = Listfirst.Intersect(Listsecond)

How to use an object from try in catch - c#

I want to use an object in catch block, which get me an exception in try block. I'm parsing some strings to int and need to catch the exception when it's impossible and see, what object was mistaken and in what line. Is that possible or not?
Some code dor example. Thanks.
static void Main(string[] args)
{
var result = Parse(new List<string>() { "3;5;7", "qwe;3;70" });
}
public static List<int[]> Parse(List<string> list)
{
try
{
return list.Select(str => str.Split(';'))
.Select(str => Tuple.Create(int.Parse(str[0]), int.Parse(str[1]), int.Parse(str[2])))
/// something happening
.ToList();
}
catch
{
//here in braces I want to know, which element was wrong
//"qwe" and whole line "qwe;3;70"
throw new FormatException($"Wrong line [{}]");
}
}
Declare the line and value item counters outside the try/catch block and increase them in the LINQ expression body:
public static List<int[]> Parse(List<string> list)
{
int line = 0;
int item = 0;
try
{
return list
.Select(str => {
line++;
item = 0;
return str
.Split(';')
.Select(i => { item++; return int.Parse(i); })
.ToArray();
})
.ToList();
}
catch
{
throw new FormatException($"Wrong line [{line}]; item [{item}]");
}
}
Demo: https://dotnetfiddle.net/uGtw7A
You need a reference to the object causing the exception. However as the instance lives only in the scope of the try-block you can´t access it any more (try and catch don´t share the same scope and thus can´t access the same variables) unless you´d declare the reference to that instance outside the try-bloc
As already mentioned in the comments you should use a normal foreach-loop to have access to the current line:
public static List<int[]> Parse(List<string> list)
{
var result = new List<int[]>();
foreach(var str in list)
{
try
{
var values = str.Split(';');
result.Add(Tuple.Create(
int.Parse(values[0]),
int.Parse(values[1]),
int.Parse(values[2]))
);
}
catch
{
//here in braces I want to know, which element was wrong
throw new FormatException($"Wrong line " + str");
}
}
return result;
}
However you can simply avoid all those exceptions by useing TryParse instead which returns false if parsing failed. So this boils down to something like this:
var values = str.Split(';');
int v0, v1, v2;
if(int.TryParse(values[0], out v0 &&
int.TryParse(values[1], out v1 &&
int.TryParse(values[2], out v2 &&))
result.Add(Tuple.Create(v0, v1, v2));
else
throw new FormatException($"Wrong line " + str");
I recommend manually looping through, splitting the data, checking you have enough elements, and then using TryParse on the numbers. I know this is a departure from using Linq, but it's the better way to do this with error checking:
public static List<int[]> Parse(List<string> list)
{
if (list == null)
{
throw new ArgumentNullException("list");
// you can use nameof(list) instead of "list" in newer versions of C#
}
List<int[]> result = new List<int[]>();
// Loop through the entries
for (int i = 0; i < list.Count; ++i)
{
// Be safe and check we don't have a null value
// I'm just skipping the 'bad' entries for now but
// you can throw an error, etc.
if (list[i] == null)
{
// do something about this? (an exception of your choosing, etc.)
continue;
}
// split the entry
string[] entryData = list[i].Split(';');
// check we have 3 items
if (entryData.Length != 3)
{
// do something about this?
continue;
}
// try to parse each item in turn
int a;
int b;
int c;
if (!int.TryParse(entryData[0], out a))
{
// do something about this?
continue;
}
if (!int.TryParse(entryData[1], out b))
{
// do something about this?
continue;
}
if (!int.TryParse(entryData[2], out c))
{
// do something about this?
continue;
}
// add to the results list
result.Add(new int[] { a, b, c });
}
// return the result
return result;
}
Scope is scope. Anything you define inside your try block and don't explicitly pass on is not going to be available in your catch block.
If you need this information you have to iterate manually over the list and try catch each attempt individually...
There are too many problems with your code, you're assuming that parameter list is not null and contains items that can be splitted in 3 strings, and that every string can be safely parsed to int.
If you not have all the above guaranties just check everything:
public static List<int[]> Parse(List<string> list)
{
if (list == null)
{
throw new ArgumentNullException(nameof(list));
}
var arrayOfStringArray = list
.Select(x => x.Split(';'))
.ToArray();
var resultList = new List<int[]>();
for (var i = 0; i < arrayOfStringArray.Length; i++)
{
var arrayOfString = arrayOfStringArray[i];
if (arrayOfString.Length != 3)
{
throw new InvalidOperationException("meaningfull message there!");
}
var arrayOfInt = new int[3];
for (var j = 0; j < arrayOfInt.Length; j++)
{
arrayOfInt[j] = TryParse(arrayOfString[j], i, j);
}
resultList.Add(arrayOfInt);
}
return resultList;
}
static int TryParse(string value, int line, int position)
{
int result;
if (!int.TryParse(value, out result))
{
throw new FormatException($"Item at position {line},{position} is invalid.");
}
return result;
}
I think that you just got a wrong approach here. Yes, using Tuple + Linq would be the laziest way to get your result but you can't generate custom errors as so.
Here is an example of how you can achieve something alike:
static void Main(string[] args)
{
var result = Parse(new List<string>() { "3;5;7", "qwe;3;70" });
}
public static List<Tuple<int, int, int>> Parse(List<string> list)
{
List<Tuple<int, int, int>> result = new List<Tuple<int, int, int>>();
int line = 0;
int errorCol = 0;
try
{
for (line = 0; line < list.Count; line++)
{
string[] curentLine = list[line].Split(';');
int result0, result1, result2;
errorCol = 1;
if (curentLine.Length > 0 && int.TryParse(curentLine[0], out result0))
errorCol = 2;
else
throw new Exception();
if (curentLine.Length > 1 && int.TryParse(curentLine[1], out result1))
errorCol = 3;
else
throw new Exception();
if (curentLine.Length > 2 && int.TryParse(curentLine[2], out result2))
result.Add(new Tuple<int, int, int>(result0, result1, result2));
else
throw new Exception();
}
return result;
}
catch
{
//here in braces I want to know, which element was wrong
throw new FormatException("Wrong line " + line + " col" + errorCol);
}
}
PS: Line and column start at 0 here.

Returning the smallest integer in an arrayList in C#

I recently got asked in a interview to create an method where the following checks are to be made:
Code to check if ArrayList is null
Code to loop through ArrayList objects
Code to make sure object is an integer
Code to check if it is null, and if not then to compare it against a variable containing the smallest integer from the list and if smaller then
overwrite it.
Return the smallest integer in the list.
So I created the following method
static void Main(string[] args)
{
ArrayList list = new ArrayList();
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);
list.Add(5);
Program p = new Program();
p.Min(list);
}
private int? Min(ArrayList list)
{
int value;
//Code to check if ArrayList is null
if (list.Count > 0)
{
string minValue = GetMinValue(list).ToString();
//Code to loop through ArrayList objects
for(int i = 0; i < list.Count; i++)
{
//Code to make sure object is an integer
//Code to check if it is null, and if not to compare it against a variable containing the
//smallest integer from the list and if smaller overwrite it.
if (Int32.TryParse(i.ToString(), out value) || i.ToString() != string.Empty)
{
if (Convert.ToInt32(list[i]) < Convert.ToInt32(minValue))
{
minValue = list[i];
}
}
}
}
return Convert.ToInt32(GetMinValue(list));
}
public static object GetMinValue(ArrayList arrList)
{
ArrayList sortArrayList = arrList;
sortArrayList.Sort();
return sortArrayList[0];
}
I think the above is somewhat correct, however am not entirely sure about 4?
I think The following logic may help you. It is simpler than the current and are using int.TryParse() for parsing, which is better than Convert.To..() and int.Parse() Since it has some internal error handling and hence it will will not throw any exception for invalid input. If the input is invalid then it gives 0 to the out variable and returns false, From that we can assume the conversion failed. See the code for this:
var arrayMin = listOfInt;
int currentNum = 0;
int yourNum = int.MaxValue;
bool isSuccess = true;
foreach (var item in listOfInt)
{
if (int.TryParse(item.ToString(), out currentNum) && currentNum <= yourNum)
{
yourNum = currentNum;
}
else
{
isSuccess = false;
break;
}
}
if(isSuccess)
Console.WriteLine("Minimum Number in the array is {0}",yourNum);
else
Console.WriteLine("Invalid input element found");
Simplistic version:
private int? Min(ArrayList list)
{
if (list == null || list.Count == 0) return null;
return list.Cast<int>().Min();
}

C# Finding elements from a list to match each elements from another list

The idea is that I have an object GrossPanel that has a property GrossPanel.PanelListthat contains a list of Panelobjects ;List<Panel>
Each Panelobject has the property of type double Panel.Prod_Width
What I want to do is to match each Panel.Prod_Widthin the inputto each Panel.Prod_Widthin the template.PanelList
When a match is found, the Panelfrom the inputlist is put into a new GrossPanelobject and removed frominput. If a complete matching set is found the resulting GrossPanelis added to the _Returnlist and everyting is repeated until the input list is exhausted.
Example:
Lets say the inputcontains 9 elements (Panel0-Panel8) and templatecontains 2 elements (temp0-temp1)
Panel0-Panel3 has Prod_Width = 200
Panel4-Panel7 has Prod_Width = 300
Panel8 has Prod_Width = 400
temp0 has Prod_Width = 200 and temp1 has Prod_Width = 300
This should create 4 GrossPanelobjects, GP0-GP3
GP0 should contain Panel0 and Panel4
GP1 should contain Panel1 and Panel5
GP2 should contain Panel2 and Panel6
GP3 should contain Panel3 and Panel7
Panel8 can't be used
This is the code I have written to do this. It works, but it is very slow.
Is there a way to do this more efficient? I tried to do a foreach loop and removing elements from inputalong the way, but it din't work. Instead I use Indexand _index to skip the "used" elements in input
private static List<GrossPanel> Match (List<Panel> input, GrossPanel template)
{
List<Panel> _template = template.PanelList.OrderBy(panel => panel.Prod_Width).ToList();
List<Panel> _input = input.OrderBy(panel => panel.Prod_Width).ToList();
List<GrossPanel> _Returnlist = new List<GrossPanel>();
List<int> indexlist = new List<int>(); // list of used indexes
int Index = 0; //counting the panels you have checked
while (Index < _input.Count)
{
int _index = 0;
GrossPanel Grosspanel = new GrossPanel();
for (int templateindex = 0; templateindex < _template.Count(); templateindex++)
{
for (int inputindex = _index; inputindex < _input.Count(); inputindex++)
{
if ((!indexlist.Contains(inputindex)) && (_template.ElementAt(templateindex).Prod_Width == _input.ElementAt(inputindex).Prod_Width))
{
indexlist.Add(inputindex);
Grosspanel.AddNetPanel(input.ElementAt(inputindex));
_index = indexlist.Last(); //
Index++;
break;
}
}
}
if (Grosspanel.NetPanelCount == _template.Count()) _Returnlist.Add(Grosspanel);
else if (Grosspanel.NetPanelCount != _template.Count()) Index = _input.Count;
}
return _Returnlist;
}
OK...
I tried to use IEnuberable and yield return to make this quicker. My problem now is that when I find a match in input I can't seem to remove it from input in the next iteration.
here is the code
private static IEnumerable<GrossSteniPanel> Match (IEnumerable<Panel> input, GrossPanel template, List<Panel> usedpanels, int index)
{
GrossPanel Grosspanel;
List<Panel> _usedpanels = new List<Panel>();
IEnumerable<Panel> _input = input;
_input = _input.Except(usedpanels);
if (index < 0 | (_input.Count() == 0)) yield return Grosspanel = new GrossPanel();
else
{
foreach (Panel p in _input)
{
if (p.Prod_Width == template.NetPanelList.ElementAt(index).Prod_Width)
{
_usedpanels.Add(p);
_input = _input.Except(_usedpanels);
foreach (GrossPanel panel in Match (_input, template, usedpanels, index - 1))
{
Grosspanel = panel;
Grosspanel.AddNetPanel(p);
yield return Grosspanel;
}
}
}
}
}
What am I missing??
My recommendations:
Try to make your code easier to read and understand (in 99% of the cases this is more important than performance).
Use one convention when naming variables. I found 4 different naming conventions in first 5 lines of "Match" method.
Using underline before local variable name is not good.
try to write tests for "Match" method.
Refactor example (name "Match" changed to "BuildGrossPanelList"):
static IList<GrossPanel> BuildGrossPanelList(List<Panel> input, GrossPanel template)
{
var templatePanels = template.PanelList
.OrderBy(panel => panel.Width);
var inputPanels = input
.OrderBy(panel => panel.Width)
.ThenBy(panel => panel.Id);
// If `input` can have elements with the same `panel.Width`
// and you want to always retun the same result then the sorting has to be extend.
var templatesWithMatchingPanels = templatePanels
.ToDictionary(
tp => tp,
tp => inputPanels.Where(p => p.Width == tp.Width).ToList());
return GetGrossPanels(templatesWithMatchingPanels);
}
static IList<GrossPanel> GetGrossPanels(Dictionary<Panel, List<Panel>> templatesWithMatchingPanels)
{
var result = new List<GrossPanel>();
while(AnyNotUsedPanelExistsForEveryTemplate(templatesWithMatchingPanels))
{
result.Add(CreateNewGrossPanel(templatesWithMatchingPanels));
}
return result;
}
static bool AnyNotUsedPanelExistsForEveryTemplate(Dictionary<Panel, List<Panel>> templatesWithMatchingPanels)
{
return templatesWithMatchingPanels.All(entry => entry.Value.Any());
}
static GrossPanel CreateNewGrossPanel(Dictionary<Panel, List<Panel>> templatesWithMatchingPanels)
{
var result = new GrossPanel();
foreach(var templatePanelEntry in templatesWithMatchingPanels)
{
var firstMatchingPanel = GetAndRemoveFirst(templatePanelEntry.Value);
result.AddNetPanel(firstMatchingPanel);
}
return result;
}
static Panel GetAndRemoveFirst(IList<Panel> panels)
{
var result = panels.First();
panels.RemoveAt(0);
return result;
}
If "Match" method is part of a large class at least put the above code in a nested class. Consider creating a new class in a separate file. Methods in this new class wouldn't have to be static.

MVCCrud Using LinqToEntities

There is a sample application called MVCCrud. This example is quite good and I would like to use it as the framework on a project that I am working on.
The problem is that MVCCrud uses LingToSQL and I would like to use LinqToEntities. I got most everything to work correctly once I converted over to LinqToEntities except one place.
In the following code on the lines i = typeof(TModel).GetProperty(primaryKey).GetValue(p, null),
cell = getCells(p)
it gives a Linq to Entities does not recognize GetValue.
Can someone help me refactor the following code?
items = items.OrderBy(string.Format("{0} {1}", sidx, sord)).Skip(pageIndex * pageSize).Take(pageSize).AsQueryable();
// Generate JSON
var jsonData =
new
{
total = totalPages,
page,
records = totalRecords,
rows = items.Select(
p => new
{
// id column from repository
i = typeof(TModel).GetProperty(primaryKey).GetValue(p, null),
cell = getCells(p)
}).ToArray()
};
return Json(jsonData);
and here is the getCell method:
private string[] getCells(TModel p)
{
List<string> result = new List<string>();
string a = actionCell(p);
if (a != null)
{
result.Add(a);
}
foreach (string column in data_rows.Select(r => r.value))
{
try
{
// hack for tblcategory.name
string[] parts = column.Split('.');
// Set first part
PropertyInfo c = typeof(TModel).GetProperty(parts[0]);
object tmp = c.GetValue(p, null);
// loop through if there is more than one depth to the . eg tblCategory.name
for (int j = 1; j < parts.Length; j++)
{
c = tmp.GetType().GetProperty(parts[j]);
tmp = c.GetValue(tmp, null);
}
if (tmp.GetType() == typeof(DateTime))
{
result.Add(((DateTime)tmp).ToString(dateTimeFormat));
}
else if (tmp.GetType() == typeof(float))
{
result.Add(((float)tmp).ToString(decimalFormat));
}
else if (tmp.GetType() == typeof(double))
{
result.Add(((double)tmp).ToString(decimalFormat));
}
else if (tmp.GetType() == typeof(decimal))
{
result.Add(((decimal)tmp).ToString(decimalFormat));
}
else
{
result.Add(tmp.ToString());
}
}
catch (Exception)
{
result.Add(string.Empty);
}
}
return result.ToArray();
}
Do this ToList() instead of AsQueryable():
items = items.OrderBy(string.Format("{0} {1}", sidx, sord)).Skip(pageIndex * pageSize).Take(pageSize).ToList();
You can't execute any external method "within" linq query.
And may you say that was working in Linq2Sql then you should know when you call any external method "Like ToString()" Linq2Sql will fetch all data from database then handle your query in the memory and that maybe a serious harming if you have a lot of records.
For more information look at this

Categories