C# Get accessor is inaccessible - c#

I have the following class definition:
public static string SplitString(string someText)
{
var queryArray = Regex.Split(someText, "\\s+(?=\\w+)");
foreach (var i in Enumerable.Range(0, queryArray.Count - 1)) {
// Some code
}
}
The problem is that queryArray.Count is giving me the following error:
The property 'System.Array.Count' cannot be used in this context because the get accessor is inaccessable.
What am i missing here?

You may try the Length property instead:
public static string SplitString(string someText)
{
var queryArray = Regex.Split(someText, "\\s+(?=\\w+)");
foreach (var i in Enumerable.Range(0, queryArray.Length - 1)) {
// Some code
}
}
Also your code would probably have been more readable if it was written like this:
public static string SplitString(string someText)
{
var queryArray = Regex.Split(someText, "\\s+(?=\\w+)");
for (var i = 0; i < queryArray.Length; i++) {
// Some code
}
}
or like this:
public static string SplitString(string someText)
{
var queryArray = Regex.Split(someText, "\\s+(?=\\w+)");
foreach (var item in queryArray) {
// Some code
}
}

Regex.Split returns an array, which doesn't define a Count property. Use Length instead:
public static string SplitString(string someText)
{
var queryArray = Regex.Split(someText, "\\s+(?=\\w+)");
foreach (var i in Enumerable.Range(0, queryArray.Length - 1)) {
// Some code
}
}

You can try with Length property

Why worry about an index when the Select extension will get it for you:
var data = Regex.Split("someText other", "\\s+(?=\\w+)")
.Select((itm, indexer) => string.Format("{0} is index {1}", itm, indexer));
/* Data has 2 strings in the list:
someText is index 0
other is index 1
*/

Related

How to compare the contents of two arrays and returning the index of the duplicated file?

I've made a method that compares the files within two file directories and it returns if there are files that are duplicated in the form of a bool. However, would actually want it to return the files name or the index of the file in its array so I can then delete the file so their are no complications when moving files into one directory. I've tried to cast the "==" compare statement to a string hoping it would give the files name but I forgot since its a boolean operation it will only return true or false.
static public string ModFileDupilcate(string[] SimsModDownloadDirectory, string[] SimsModsDirectory)
{
string NoDuplicateMods = "There are no duplicate mods";
foreach (var ModInDownloadDirectory in SimsModDownloadDirectory)
{
foreach (var ModInModsDirectory in SimsModsDirectory)
{
if (ModInDownloadDirectory == ModInModsDirectory)
{
string DuplicateMod = (ModInDownloadDirectory == ModInModsDirectory).ToString();
return DuplicateMod;
}
else
{
return NoDuplicateMods;
}
}
}
return NoDuplicateMods;
}
You can get the indexes of the matching strings with something like this
var result = SimsModDownloadDirectory.Select((x, i) =>
{return (SimsModsDirectory.Contains(x) ? i :-1);})
.Where(x => x != -1);
foreach(int index in result)
Console.WriteLine(index);
The idea is the following:
Enumerate with Select all the strings (x) in the first list with the overload that gives us also the index of the enumerated string (i), if the enumerated string is contained in the second list return its index otherwise return -1. Finally take with Where only the not -1 values extracted by the Select
Of course returning only the names of the duplicates is a lot more simple
var result = SimsModDownloadDirectory.Intersect(SimsModsDirectory);
foreach(string name in result)
Console.WriteLine(name);
These approaches are based on the exact match in case between the two strings to compare. So a string "Steve" will not match a string "steve".
If your requirements are to ignore case in the comparison then you could change to
var result = SimsModDownloadDirectory.Select((x, i) =>
{
return (SimsModsDirectory.Contains(x,
StringComparer.CurrentCultureIgnoreCase) ? i :-1);
}).Where(x => x != -1);
or to
var result = SimsModDownloadDirectory.Intersect(SimsModsDirectory,
StringComparer.CurrentCultureIgnoreCase);
The else in your code is the issue.
Sample code (untested)
static public string ModFileDupilcate(string[] SimsModDownloadDirectory, string[] SimsModsDirectory)
{
string NoDuplicateMods = "There are no duplicate mods";
foreach (var ModInDownloadDirectory in SimsModDownloadDirectory)
{
foreach (var ModInModsDirectory in SimsModsDirectory)
{
if (ModInDownloadDirectory == ModInModsDirectory)
{
return ModInModsDirectory;
}
}
}
return NoDuplicateMods;
}
The above only returns the first duplicate. For all duplicates, you have to maintain a list and return that at the end
static public List<string> ModFileDupilcate(string[] SimsModDownloadDirectory, string[] SimsModsDirectory)
{
var duplicateDirs = new List<string>();
foreach (var ModInDownloadDirectory in SimsModDownloadDirectory)
{
foreach (var ModInModsDirectory in SimsModsDirectory)
{
if (ModInDownloadDirectory == ModInModsDirectory)
{
duplicateDirs.Add(ModInModsDirectory);
}
}
}
return duplicateDirs;
}
I don't exactly know what are you trying to achieve. Your code does not tell us what should the return value be. If you want to tell the caller that "There is/isn't duplicate file names", you can easily return bool. If you want to return the "duplicate file names", you should return string[] or FileInfo[] or IReadOnlyCollection<string> or something similar. The advantage of returning a collection or array, is that the caller can easily see that if there is/isn't any duplicates, by checking the Length/Count of the returned value.
Using nested for loops, has a poor performance of O(n*m). Using a HashSet or LINQ's Intersect method, you can easily achieve the goal in O(n+m):
public static IReadOnlyList<string> FindDuplicateModFiles(string[] SimsModDownloadDirectory, string[] SimsModsDirectory)
{
var set = new HashSet<string>(SimsModDownloadDirectory);
var result = new List<string>();
foreach (string file in SimsModsDirectory)
{
if (set.Contains(file))
result.Add(file);
}
return result.AsReadOnly();
}
Or using LINQ:
public static IEnumerable<string> FindDuplicateModFiles2(string[] SimsModDownloadDirectory, string[] SimsModsDirectory)
{
return SimsModDownloadDirectory.Intersect(SimsModsDirectory);
}
If you want to remove the duplicates from the first collection, the best options is the LINQ's Except method:
public static IEnumerable<string> GetNonDuplicatesInFirst(string[] SimsModDownloadDirectory, string[] SimsModsDirectory)
{
return SimsModDownloadDirectory.Except(SimsModsDirectory);
}
static public IEnumerable<string> ModFileDupilcate(string[] SimsModDownloadDirectory,
string[] SimsModsDirectory)
{
var result = SimsModDownloadDirectory.Select((x, i) =>
SimsModsDirectory.Contains(x) ? x : string.Empty).
Where(x => !string.IsNullOrEmpty(x));
return result;
}
Call method like :
var resultOfDublicateFiles = ModFileDupilcate(SimsModDownloadDirectory,SimsModsDirectory);
Or
public static bool ModFileDupilcate(string[] SimsModDownloadDirectory,
List<string> SimsModsDirectory,out List<string> dublicatedFiles)
{
dublicatedFiles = new List<string>();
foreach (var ModInDownloadDirectory in SimsModDownloadDirectory)
{
foreach (var ModInModsDirectory in SimsModsDirectory)
{
if (ModInDownloadDirectory == ModInModsDirectory)
{
dublicatedFiles.Add(ModInModsDirectory);
}
}
}
return dublicatedFiles.Count > 0;
}
Call method like :
List<string> dublicatedFiles;
bool hasDublicatedFiles= ModFileDupilcate(new string["a","b","c"],new string["b","c","d","f"],out dublicatedFiles);

Sort Array on on Value Difference

I Have An Array,for example
string[] stArr= new string[5] { "1#3", "19#24", "10#12", "13#18", "20#21" };
i want to sort this array on
3-1=2;
24-19=5;
12-10=2;
18-13=5;
21-20=1;
and the sorting result should be like
string[] stArr= new string[5] { "20#21", "1#3", "10#12", "13#18", "20#21" };
I have to find the solution for all possible cases.
1>length of the array is not fixed(element in the array)
2>y always greater than x e.g x#y
3> i can not use list
You can use LINQ:
var sorted = stArr.OrderBy(s => s.Split('#')
.Select(n => Int32.Parse(n))
.Reverse()
.Aggregate((first,second) => first - second));
For Your Case:
stArr = stArr.OrderBy(s => s.Split('#')
.Select(n => Int32.Parse(n))
.Reverse()
.Aggregate((first,second) => first - second)).ToArray();
try this
string[] stArr = new string[5] { "1#3", "19#24", "10#12", "13#18", "20#21" };
Array.Sort(stArr, new Comparison<string>(compare));
int compare(string z, string t)
{
var xarr = z.Split('#');
var yarr = t.Split('#');
var x1 = int.Parse(xarr[0]);
var y1 = int.Parse(xarr[1]);
var x2 = int.Parse(yarr[0]);
var y2 = int.Parse(yarr[1]);
return (y1 - x1).CompareTo(y2 - x2);
}
Solving this problem is identical to solving any other sorting problem where the order is to be specified by your code - you have to write a custom comparison method, and pass it to the built-in sorter.
In your situation, it means writing something like this:
private static int FindDiff(string s) {
// Split the string at #
// Parse both sides as int
// return rightSide-leftSide
}
private static int CompareDiff(string a, string b) {
return FindDiff(a).CompareTo(FindDiff(b));
}
public static void Main() {
... // Prepare your array
string[] stArr = ...
Array.Sort(stArr, CompareDiff);
}
This approach uses Array.Sort overload with the Comparison<T> delegate implemented in the CompareDiff method. The heart of the solution is the FindDiff method, which takes a string, and produces a numeric value which must be used for comparison.
you can try the following ( using traditional way)
public class Program
{
public static void Main()
{
string[] strArr= new string[5] { "1#3", "19#24", "10#12", "13#18", "20#21" };
var list = new List<Item>();
foreach(var item in strArr){
list.Add(new Item(item));
}
strArr = list.OrderBy(t=>t.Sort).Select(t=>t.Value).ToArray();
foreach(var item in strArr)
Console.WriteLine(item);
}
}
public class Item
{
public Item(string str)
{
var split = str.Split('#');
A = Convert.ToInt32(split[0]);
B = Convert.ToInt32(split[1]);
}
public int A{get; set;}
public int B{get; set;}
public int Sort { get { return Math.Abs(B - A);}}
public string Value { get { return string.Format("{0}#{1}",B,A); }}
}
here a working demo
hope it will help you
Without LINQ and Lists :) Old School.
static void Sort(string [] strArray)
{
try
{
string[] order = new string[strArray.Length];
string[] sortedarray = new string[strArray.Length];
for (int i = 0; i < strArray.Length; i++)
{
string[] values = strArray[i].ToString().Split('#');
int index=int.Parse(values[1].ToString()) - int.Parse(values[0].ToString());
order[i] = strArray[i].ToString() + "," + index;
}
for (int i = 0; i < order.Length; i++)
{
string[] values2 = order[i].ToString().Split(',');
if (sortedarray[int.Parse(values2[1].ToString())-1] == null)
{
sortedarray[int.Parse(values2[1].ToString())-1] = values2[0].ToString();
}
else
{
if ((int.Parse(values2[1].ToString())) >= sortedarray.Length)
{
sortedarray[(int.Parse(values2[1].ToString())-1) - 1] = values2[0].ToString();
}
else if ((int.Parse(values2[1].ToString())) < sortedarray.Length)
{
sortedarray[(int.Parse(values2[1].ToString())-1) + 1] = values2[0].ToString();
}
}
}
for (int i = 0; i < sortedarray.Length; i++)
{
Console.WriteLine(sortedarray[i]);
}
Console.Read();
}
catch (Exception ex)
{
throw;
}
finally
{
}

Find the first non-repeated character in a string using C#

I am working to solve this problem. I have to find the first nonrepeated character in a string.
For example,
Input : “teeter”
Output: r
I am going to first use HashTables :
class Program
{
static void Main()
{
var inputString = “teeter” ;
Hashtable hashtable = new Hashtable();
int numb = 1;
for (int i=0; i< inputString.length(); i++)
{
if (!hashtable.ContainsKey(hashtable[i]))
hashtable.Add(hashtable[i], numb);
else
hashtable[hashtable[i]] = hashtable[i].Value+ 1 ;
}
}
}
Can I solve this problem using LinQ:
numb = inputString.First(1 == inputString.Where(item =>
item == hashtable[i]).Count());
My questions are :
-I have to solve this problem using LINQ and using HashTables or Dictionaries. Does my solutions ture ?
// throws an ArgumentNullException if s is null.
// throws an InvalidOperationException if there is no non repeating character.
char FirstNonRepeater(string s)
{
return s.ToLookup(c => c).First(g => g.Count() == 1).Key;
}
I don't think you need HashTable at all. Because string implements IEnumerable<char> you can use LINQ directly on your input string:
var letter = input.GroupBy(x => x).First(g => g.Count() == 1).Key;
Getting back to your HashTable solution. You 're not using it correctly. HashTable is not the same as Dictionary. It does not have key/value, it just has keys. You're looking for Dictionary here:
var inputString = "teeter";
var dict = new Dictionary<char, int>();
int numb = 1;
for (int i=0; i< inputString.length(); i++)
{
if (!dict.ContainsKey(inputString[i]))
dict.Add(inputString[i], numb);
else
dict[inputString[i]] += 1;
}
For a solution without HashTables, Dictionaries or LINQ, just remove duplicate characters from the string:
while (s.IndexOf(s[0], 1) != -1) {
s = s.Replace(s[0].ToString(), "");
}
char result = s[0];
You can check which characters are occured only once, and take first one out of these.
var inputString = “teeter” ;
var output = inputString.GroupBy(x=>x).FirstOrDefault(x=>x.Count() ==1).Key;
class Program
{
public static void Main(string[] args)
{
Console.WriteLine(FirstNonRepeated("tether"));
Console.ReadKey();
}
public static char? FirstNonRepeated(string word)
{
char[] chararray= word.ToCharArray();
Hashtable hashtable=new Hashtable();
foreach (var c in chararray)
{
if (hashtable.ContainsKey(c))
{
hashtable[c]=(int)hashtable[c]+1;
}
else
{
hashtable.Add(c,1);
}
}
foreach (var v in chararray)
{
if ((int) hashtable[v] == 1)
{
return v;
}
}
return null;
}
}

Foreach loop for three List<string>

I want to loop through three List<string>. I'm sending ajax request containing 3 parameter as Array.
This is my WebMethod.
public string saveEachTask(string imageData, string desc, string tid)
{
var imglist = imageData.Split(',').ToList();
var desclist = desc.Split(',').ToList();
var idlist = tid.Split(',').ToList();
// here i want a foreach loop for above three list
return "Saved Succesfully";
}
Edit: in loop how can I identity which string is for img, desc and id
Any Help appreciated.
Perhaps something like this:
foreach (var list in new[] {imglist, desclist, idlist})
{
foreach (var s in list)
{
}
}
Use one loop and each iteration process each list.
public string saveEachTask(string imageData, string desc, string tid)
{
var imglist = imageData.Split(',').ToList();
var desclist = desc.Split(',').ToList();
var idlist = tid.Split(',').ToList();
int maxLength = Math.Max(imglist.Count, Math.Max(desclist.Count, idlist.Count));
for (int i = 0; i < maxLength; ++i)
{
string imgItem = (i < imglist.Count ? imglist[i] : null);
string descItem = (i < desclist.Count ? desclist[i] : null);
string idItem = (i < idlist.Count ? idlist[i] : null);
// TODO: Process imgItem, descItem, idItem
}
return "Saved Succesfully";
}
If you need to handle everything the same way in your loop, you could try:
foreach(var s in imglist.Union(desclist.Union(idlist)))
{
// do something with the string
}

How to delete last character in a string in C#?

Building a string for post request in the following way,
var itemsToAdd = sl.SelProds.ToList();
if (sl.SelProds.Count() != 0)
{
foreach (var item in itemsToAdd)
{
paramstr = paramstr + string.Format("productID={0}&", item.prodID.ToString());
}
}
after I get resulting paramstr, I need to delete last character & in it
How to delete last character in a string using C#?
Personally I would go with Rob's suggestion, but if you want to remove one (or more) specific trailing character(s) you can use TrimEnd. E.g.
paramstr = paramstr.TrimEnd('&');
build it with string.Join instead:
var parameters = sl.SelProds.Select(x=>"productID="+x.prodID).ToArray();
paramstr = string.Join("&", parameters);
string.Join takes a seperator ("&") and and array of strings (parameters), and inserts the seperator between each element of the array.
string source;
// source gets initialized
string dest;
if (source.Length > 0)
{
dest = source.Substring(0, source.Length - 1);
}
Try this:
paramstr.Remove((paramstr.Length-1),1);
I would just not add it in the first place:
var sb = new StringBuilder();
bool first = true;
foreach (var foo in items) {
if (first)
first = false;
else
sb.Append('&');
// for example:
var escapedValue = System.Web.HttpUtility.UrlEncode(foo);
sb.Append(key).Append('=').Append(escapedValue);
}
var s = sb.ToString();
string str="This is test string.";
str=str.Remove(str.Length-1);
It's better if you use string.Join.
class Product
{
public int ProductID { get; set; }
}
static void Main(string[] args)
{
List<Product> products = new List<Product>()
{
new Product { ProductID = 1 },
new Product { ProductID = 2 },
new Product { ProductID = 3 }
};
string theURL = string.Join("&", products.Select(p => string.Format("productID={0}", p.ProductID)));
Console.WriteLine(theURL);
}
It's good practice to use a StringBuilder when concatenating a lot of strings and you can then use the Remove method to get rid of the final character.
StringBuilder paramBuilder = new StringBuilder();
foreach (var item in itemsToAdd)
{
paramBuilder.AppendFormat(("productID={0}&", item.prodID.ToString());
}
if (paramBuilder.Length > 1)
paramBuilder.Remove(paramBuilder.Length-1, 1);
string s = paramBuilder.ToString();
paramstr.Remove((paramstr.Length-1),1);
This does work to remove a single character from the end of a string. But if I use it to remove, say, 4 characters, this doesn't work:
paramstr.Remove((paramstr.Length-4),1);
As an alternative, I have used this approach instead:
DateFrom = DateFrom.Substring(0, DateFrom.Length-4);
Add a StringBuilder extension method.
public static StringBuilder RemoveLast(this StringBuilder sb, string value)
{
if(sb.Length < 1) return sb;
sb.Remove(sb.ToString().LastIndexOf(value), value.Length);
return sb;
}
then use:
yourStringBuilder.RemoveLast(",");

Categories