I have a dictionary. Everything is working fine but sorting. I have even tried a SortedDictionary.
Here's what I am doing, I have a Dictionary that contains FilePath,FileName alright.
Well I am trying to sort by the Value and then put then put the (Keys) into a list.
Here is my code. (UPDATED: ENTIRE METHOD).
public static void DisplayScriptListNames(){
scriptsList.Clear ();
fileInfo = new DirectoryInfo (Application.dataPath);
if (EclecticGlobalSettings._cSharp && isSharp) {
sharpFiles = fileInfo.GetFiles ("*.cs", SearchOption.AllDirectories).ToList();
} if(EclecticGlobalSettings._usScripts && !isSharp) {
javaFiles = fileInfo.GetFiles ("*.js", SearchOption.AllDirectories).ToList();
}
if (EclecticGlobalSettings._cSharp && isSharp) {
// C#
if (sharpFiles.Count != 0) {
foreach (FileInfo i in sharpFiles){
string line = i.Name.ToString ();
string checkPath = Path.GetDirectoryName (i.FullName);
string assetsPath = checkPath.Substring (i.FullName.IndexOf ("Assets"));
if (!assetsPath.Contains("Editor") && !assetsPath.Contains("Standard Assets")) {
scriptDictionary.Add(i.FullName,i.Name);
scriptsFound += 1;
}
}
}
}
if(EclecticGlobalSettings._usScripts && !isSharp){
//JS
foreach (FileInfo i in javaFiles) {
//string line = i.FullName.ToString ();
string line = i.Name.ToString ();
string checkPath = Path.GetDirectoryName (i.FullName);
string assetsPath = checkPath.Substring (i.FullName.IndexOf ("Assets"));
if (!assetsPath.Contains("Editor") && !assetsPath.Contains("Standard Assets")) {
Debug.Log (i.Name);
scriptDictionary.Add(i.FullName,i.Name);
scriptsFound += 1;
}
}
}
foreach (KeyValuePair<string,string> item in scriptDictionary.OrderBy(key=>key.Value)) {
Debug.Log (item);
scriptsList.Add (item.Key);
}
//scriptsList.AddRange (scriptDictionary.Keys);
//scriptsList.Sort (Path.GetFileName);
//foreach (string ii in scriptsList) {
// Debug.Log (ii);
//
//}
}
Okay, the Debug.Log() is Unity's way of a Console.WriteLine. And it does in fact say it's sorting it. But when I do.
scriptsList.Add (item.Key);
It's unorganized as it was before.
Is there some simple little step I am missing? Because the console does in fact say it's sorted perfectly the way I'd like. But for some reason, the scriptsList.Add(item.key) < For the PATH to the file. Says it isn't sorted.
I would do scriptList.Sort(); But remember, the scriptList is the keys (File Paths). Which is why I've been trying to sort via Values (the file names).
Which again, says it does sort them.
Here's an example of what compiler says
C:/Cat.txt, Cat.txt. C:/Dog.txt, Dog.txt. C:/Wolf.txt,
Wolf.txt.
But when I go to add them to the list.
C:/Wolf.txt. C:/Dog.txt. C:/Cat.txt.
I figured it out guys! I feel like a total dummy.... I had left an old part of code at the top of one of my if statements, and I had, had if(scriptList.Count < 1) { Sort It }. Removed that, and now good to go :)
Related
Im struggling with a json object.
I create the object (RO) with the following code and that Works fine.
string reply = #"" + client.UploadString(url, "POST", LS_json);
RootObject RO = new RootObject();
RO = JsonConvert.DeserializeObject<RootObject>(reply);
RO now contains all the data I have recieved through the json search.
Now, when iterating through the object the foreach iterate one more than (RO) contains:
cnt_V = 0;
foreach (object obj_attributtertype in RO.hits.hits[0]._source.Biz.Rel[cnt_I].org[cnt_III].mem[cnt_IV].attributter[cnt_V].type)
{
if (Convert.ToString(RO.hits.hits[0]._source.Biz.Rel[cnt_I].mem[cnt_III].xsData[cnt_IV].attributes[cnt_V].type) == "KEY_VALUES")
{
LS_ande = "" + Convert.ToString(RO.hits.hits[0]._source.Biz.Rel[cnt_I].mem[cnt_III].xsData[cnt_IV].attributes[cnt_V].values[0].value);
}
cnt_V++;
}
The thing is that when cnt_V == 4 and "points" to the last entry attributes[cnt_V] then LS_ande is filled as supposed (=="KEY_VALUES").
But then the foreach iterates again (cnt_V == 5), no problem here, but when it is assigned to LS_ande then it dumps (of cource because there is no entry with data for cnt_V == 5).
I dont understand whats wrong. Please be gentle with me and feel free to ask for further information.
Thanks in advance.
While I can't answer this definitively because I don't have the data, this is what I would start with:
//take out the long and lengthy parts to make the rest clearer
//I see there are two things here, intentional?
var something = RO.hits.hits[0]._source.Biz.Rel[cnt_I].org[cnt_III].mem[cnt_IV].attributter;
var somethingElse = RO.hits.hits[0]._source.Biz.Rel[cnt_I].mem[cnt_III].xsData[cnt_IV].attributes;
cnt_V = 0;
//Here, you are iterating over something[cnt_V].type, but also change cnt_V in the body.
//Are you sure this is correct?
foreach (object obj_attributtertype in something[cnt_V].type)
{
if (Convert.ToString(somethingElse[cnt_V].type) == "KEY_VALUES")
{
LS_ande = "" + Convert.ToString(somethingElse[cnt_V].values[0].value);
}
cnt_V++;
}
And looking at it that way, here is my stab in the dark.
Iterate with a for over the Count() of items in something
var something = RO.hits.hits[0]._source.Biz.Rel[cnt_I].org[cnt_III].mem[cnt_IV].attributter;
var somethingElse = RO.hits.hits[0]._source.Biz.Rel[cnt_I].mem[cnt_III].xsData[cnt_IV].attributes;
for (var cnt_V = 0; cnt_V < something.Count(); ++cnt_V)
{
if (Convert.ToString(somethingElse[cnt_V].type) == "KEY_VALUES")
{
LS_ande = "" + Convert.ToString(somethingElse[cnt_V].values[0].value);
}
cnt_V++;
}
I'm trying to parse out this single method which has over 8,000 lines of hardcoded data validation. Most of which is identical, duplicated logic for different fields in the data source.
A lot of it looks something like this (C++):
temp_str = _enrollment->Fields->FieldByName("ID")->AsString.SubString(1,2);
if (temp_str.IsEmpty())
{ /* do stuff */ }
else
{
if (!IsDigitsOnly(temp_str))
{ /* do different stuff */ }
else
{ /* do other stuff */ }
}
temp_str = _enrollment->Fields->FieldByName("OtherField");
if (temp_str.IsEmpty())
/* do more stuff */
So basically, I just need to parse out values between each pair of temp_str = ... and then get each unique validation "chunk".
The problem I'm having currently is identifying where each "chunk" begins and ends.
This is the code I have:
static void Main(string[] args)
{
string file = #"C:\somePathToFile.h";
string validationHeader = "temp_str = _enrollment->Fields->FieldByName(";
string outputHeader = "=====================================================";
int startOfNextValidation;
List<string> lines = File.ReadAllLines(file).ToList<string>();
List<string> validations = new List<string>();
while (lines.Contains(validationHeader))
{
//lines[0] should be the "beginning" temp_str assignment of the validation
//lines[startOfNextValidation] should be the next temp_str assignment
startOfNextValidation = lines.IndexOf(validationHeader, lines.IndexOf(validationHeader) + 1);
//add the lines within that range to another collection
// to be iterated over and written to a textfile later
validations.Add((lines[0] + lines[startOfNextValidation]).ToString());
//remove everything up to startOfNextValidation so we can eventually exit
lines.RemoveRange(0, startOfNextValidation);
}
StreamWriter sw = File.CreateText(#"C:\someOtherPathToFile.txt");
foreach (var v in validations.Distinct())
{
sw.WriteLine(v);
sw.WriteLine(outputHeader);
}
sw.Close();
}
My while statement is never hit and it just immediately jumps to the StreamWriter creation, which creates an empty text file since validations is empty.
So I guess my first question is, how do you loop over a List while checking to make sure there are still items containing a particular "subvalue" within those items?
Edit:
I tried this as well;
while (lines.Where(stringToCheck => stringToCheck.Contains(validationHeader)))
Per this answer; https://stackoverflow.com/a/18767402/1189566
But it says it can't convert from a string to a bool?
You mean something like this?
while (lines.Any(x => x.Contains(validationHeader)))
This checks whether the validationHeader is a part of any string in the list.
I tried this as well;
while (lines.Where(stringToCheck => stringToCheck.Contains(validationHeader)))
This won't work, because LINQ's Where method will return an IEnumerable<string> in your case. And the while loop needs a boolean predicate. An IEnumerable cannot be true or false, thus the compiler is complaining.
simple one to check if it has the needed value or not
foreach (var setting in FullList)
{
if(cleanList.Exists(x => x.ProcedureName == setting.ProcedureName))
setting.IsActive = true; // do you business logic here
else
setting.IsActive = false;
updateList.Add(setting);
}
Working on an old application I see this code:, It is using DataTable, DataRow stuff.
foreach (string networkIdToCreate in networkIdsToCreate)
{
HTExtractSchema.HTProviderMedicalGroupContractRow rHTProviderMedicalGroupContract = tblHTProviderMedicalGroupContract.NewHTProviderMedicalGroupContractRow();
rHTProviderMedicalGroupContract.ItemArray = rHTProviderMedicalGroupContractDefaults.ItemArray;
rHTProviderMedicalGroupContract.NetworkId = networkIdToCreate;
rHTProviderMedicalGroupContract.Business = "470";
tblHTProviderMedicalGroupContract.Rows.Add(rHTProviderMedicalGroupContract);
}
So it creates the new row, puts some values in there and adds it to the DataTable.
Now I want to modify it to create two rows instead of one row, all values the same except for "Business" field, it is one line before the last in the code above.
So I did that like this:
foreach (string networkIdToCreate in networkIdsToCreate)
{
HTExtractSchema.HTProviderMedicalGroupContractRow rHTProviderMedicalGroupContract = tblHTProviderMedicalGroupContract.NewHTProviderMedicalGroupContractRow();
rHTProviderMedicalGroupContract.ItemArray = rHTProviderMedicalGroupContractDefaults.ItemArray;
rHTProviderMedicalGroupContract.NetworkId = networkIdToCreate;
rHTProviderMedicalGroupContract.Business = "470";
tblHTProviderMedicalGroupContract.Rows.Add(rHTProviderMedicalGroupContract);
HTExtractSchema.HTProviderMedicalGroupContractRow rHTProviderMedicalGroupContract2 = tblHTProviderMedicalGroupContract.NewHTProviderMedicalGroupContractRow();
rHTProviderMedicalGroupContract2.ItemArray = rHTProviderMedicalGroupContractDefaults.ItemArray;
rHTProviderMedicalGroupContract2.NetworkId = networkIdToCreate;
rHTProviderMedicalGroupContract2.Business = "475";
tblHTProviderMedicalGroupContract.Rows.Add(rHTProviderMedicalGroupContract2);
}
But I was wondering if there is a better way other than this copy paste? so if someone saw the code won't laugh at me :D
Just add this internal loop
foreach(var business in new[] {"470", "475"})
{
...
rHTProviderMedicalGroupContract.Business = business ;
...
}
EDIT
Or you can use a method
private void CreatRow(
string networkIdToCreate,
string business)
{
HTExtractSchema.HTProviderMedicalGroupContractRow rHTProviderMedicalGroupContract =
tblHTProviderMedicalGroupContract.NewHTProviderMedicalGroupContractRow();
rHTProviderMedicalGroupContract.ItemArray =
rHTProviderMedicalGroupContractDefaults.ItemArray;
rHTProviderMedicalGroupContract.NetworkId = networkIdToCreate;
rHTProviderMedicalGroupContract.Business = business;
tblHTProviderMedicalGroupContract.Rows.Add(rHTProviderMedicalGroupContract);
}
and use it like this
foreach (string networkIdToCreate in networkIdsToCreate)
{
CreatRow(networkIdToCreate, "470");
CreatRow(networkIdToCreate, "475");
if(networkIdToCreate == "2" || networkIdToCreate == "6")
{
CreateRow(networkIdToCreate, "474");
}
}
Note you may need to pass in tblHTProviderMedicalGroupContract depending on its scope,
I've been trying to write my own quicksort in C#.
However, when I concatenate the lower, pivot and greater partitions, Visual Studio tells me it cant convert void to string list, though I'm not sure how the concatenated lessList and moreList even becomes void.
Code snippet:
public List<string> SortFiles(List<string> fileList)
{
int listSize = fileList.Count;
if (listSize <= 1)
{
return fileList; //because it is already sorted
}
string pivotString = fileList[listSize/2];
//partition list
List<string> lessList = new List<string>();
List<string> moreList = new List<string>();
foreach (string g in fileList)
{
if (String.Compare(g, pivotString) <= 0)
{
lessList.Add(g);
}
else
{
moreList.Add(g);
}
}
lessList = SortFiles(lessList);
moreList = SortFiles(moreList);
//concatenate lessList + pivot + moreList
List<string> sortedFiles = lessList.Add(pivotString); //thinks is void
sortedFiles = sortedFiles.AddRange(moreList); //thinks is void
return sortedFiles;
The fact is that Add and AddRange don't return a new list with the added element (or range).
Rather, they add the element(s) to the list, modifying it in-place.
In fact you can simply modify the code to just do the Add and AddRange, and it will work.
Note though that it will be rather inefficient, as you are creating lists and copying thing around a lot.
I am currently making a piece of software that will allow the user to enter up to 6 directories, each directory is saved as a string (within an array) the loop is then meant to check through the array and any that are not null i.e. actually have a directory assigned are meant to be zipped into their own archive. This is the code I have so far.
private void ZipIt()
{
int nxtFileNum = 0;
string Destination = #"C:\tmpZip" + nxtFileNum + ".zip";
// Check all fields, check if empty, if not save to Selection array
// Seems a inefficient - Possibly loop through Text box control type and collect?
if (String.IsNullOrEmpty(tboxSelect1.Text) == false) { BckupArray[0] = tboxSelect1.Text; };
if (String.IsNullOrEmpty(tboxSelect2.Text) == false) { BckupArray[1] = tboxSelect2.Text; };
if (String.IsNullOrEmpty(tboxSelect3.Text) == false) { BckupArray[2] = tboxSelect3.Text; };
if (String.IsNullOrEmpty(tboxSelect4.Text) == false) { BckupArray[3] = tboxSelect4.Text; };
if (String.IsNullOrEmpty(tboxSelect5.Text) == false) { BckupArray[4] = tboxSelect5.Text; };
if (String.IsNullOrEmpty(tboxSelect6.Text) == false) { BckupArray[5] = tboxSelect6.Text; };
// Create a new ZipFile entity and then loop through each array member, checking if
// it has an assigned value, if so compress it, if not, skip it.
using (ZipFile ZipIt = new ZipFile())
{
nxtFileNum++;
foreach (String q in BckupArray)
{
if (q != null)
{
ZipIt.AddDirectory(q);
ZipIt.Comment = "This archive was created at " + System.DateTime.Now.ToString("G");
ZipIt.Save(Destination);
}
}
}
}
What I am trying to get this to do is save the first user given location to tmpZip0.7z, the second to tmpZip1.7z and so on however at the moment all it is doing is adding each directory to tmpZip0.zip.
Also as a side note, how would I get it to name each archive after the directory selected to be archived?
I am currently using DotNetZip (Ionic.Zip) dll.
I hope I gave enough information guys.
You need to switch some stuff:
foreach (String q in BckupArray)
{
nxtFileNum++;
if (q != null)
{
using (ZipFile ZipIt = new ZipFile())
{
string Destination = #"C:\tmpZip" + nxtFileNum + ".zip";
ZipIt.AddDirectory(q);
ZipIt.Comment = "This archive was created at " +
System.DateTime.Now.ToString("G");
ZipIt.Save(Destination);
}
}
}
Reasons:
The string Destination is fixed after you created it. It doesn't change, just because you increment nxtFileNum.
You created only one ZipFile and you incremented nxtFileNum only once, because the those were outside of your foreach loop
Putting the part that creates the ZipFile into the if makes sure an instance is only created if it is really used.
Well, you can do this with:
var strings = Controls.OfType<TextBox>()
.Select(x => x.Text)
.Where(text => !string.IsNullOrEmpty(text))
.ToList();
using (ZipFile ZipIt = new ZipFile())
{
nxtFileNum++;
string comment = string.Format("This archive was created at {0:G}",
DateTime.Now);
foreach (string directory in strings)
{
ZipIt.AddDirectory(directory);
ZipIt.Comment = comment;
ZipIt.Save(Destination + "." + nxtFileNum);
}
}
That will obviously pull all the textboxes though. An alternative is to have a collection of type List<TextBox> or something similar instead of the six different variables.
Note that that will always create .1, .2, .3 etc even if the user didn't specify the first three names. Let me know if you want to be absolutely faithful to the positioning the user gave.
It's not clear to me that you should really be reusing the same ZipFile object, by the way. I'd expect this to be more appropriate:
string comment = string.Format("This archive was created at {0:G}",
DateTime.Now);
int fileIndex = 0;
foreach (string directory in strings)
{
fileIndex++;
using (ZipFile zipFile = new ZipFile())
{
zipFile.AddDirectory(directory);
zipFile.Comment = comment;
zipFile.Save(Destination + "." + fileIndex);
}
}
(Note how I've renamed the variables to be more conventional, by the way - variables typically start with a lower case letter.)