I have the following String word = "12345"; I want to split each character and insert this into an int array
like this-
int[] array = { 1, 2, 3, 4, 5};
whats the fastest and easiest way to do this ?
Try using Linq:
String word = "12345";
int[] array = word
.Select(c => c - '0') // fastest conversion
.ToArray();
String word = "12345";
int[] array = word.Select(x => int.Parse(x.ToString())).ToArray();
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
public static class Extensions
{
/// <summary>
/// Creates a int array from a String.
/// </summary>
/// <param name="source">The source.</param>
/// <returns>an Int Array</returns>
public static IObservable<IEnumerable<int>> StringToIntArray(this string source)
{
return Observable.Create<IEnumerable<int>>(sub =>
{
var sourceAsStringArray = source.ToCharArray().Select(x => x.ToString());
var l = new List<int>();
foreach (var s in sourceAsStringArray)
{
int output = -1;
if (int.TryParse(s, out output))
{
l.Add(output);
}
}
sub.OnNext(l);
sub.OnCompleted();
return Disposable.Empty;
});
}
}
private async void Test()
{
var a = await "12345".StringToIntArray();
var b = await "1a234b5".StringToIntArray();
var invalid = await "IAmNotANumber".StringToIntArray();
}
Related
I succesfully parsed main entity (measure) from excel book, but I have no idea, how to set relations between measure and lookups (Cloudiness, WindDirection WeatherConditions). I also need to generate guids for lookup entities. How should I do this?
using DynamicSun.Common.Extensions;
using DynamicSun.MoscowWeather.Models;
using DynamicSun.MoscowWeather.Models.Constants;
using DynamicSun.MoscowWeather.Models.DTO;
using NPOI.SS.UserModel;
namespace DynamicSun.MoscowWeather.Infrastructure.Services;
public class WeatherExcelService
{
/// <summary>
/// Parse excel document to set of entities.
/// </summary>
public WeatherSheetDto ParseDocument(Stream file)
{
//_parsed = new WeatherSheetDto();
var documentDto = new WeatherSheetDto();
using var reader = new StreamReader(file);
var workbook = WorkbookFactory.Create(file);
for (int i = 0; i < workbook.NumberOfSheets; i++)
{
var sheet = ParseSheet(workbook.GetSheetAt(i));
documentDto.Measures.UnionWith(sheet.Measures);
documentDto.Cloudiness.UnionWith(sheet.Cloudiness);
documentDto.WindDirections.UnionWith(sheet.WindDirections);
documentDto.WeatherConditions.UnionWith(sheet.WeatherConditions);
}
return documentDto;
}
/// <summary>
/// Parse excel list to set of entities.
/// </summary>
public WeatherSheetDto ParseSheet(ISheet sheet)
{
var documentDto = new WeatherSheetDto();
foreach (IRow row in sheet)
{
if (!TryParseRow(row, out var rowDto))
{
continue;
}
documentDto.WindDirections.UnionWith(rowDto.WindDirections);
documentDto.Cloudiness.Add(rowDto.Cloudiness);
documentDto.WeatherConditions.Add(rowDto.WeatherCondition);
documentDto.Measures.Add(rowDto.Measure);
}
return documentDto;
}
/// <summary>
/// Parse excel row to set of entities.
/// </summary>
public bool TryParseRow(IRow row, out WeatherRowDTO? result)
{
try
{
var cloudiness = ParseCloudiness(row);
result = new WeatherRowDTO
{
WindDirections = ParseWindDirections(row),
Cloudiness = cloudiness,
WeatherCondition = ParseWeatherCondition(row),
Measure = ParseMeasure(row),
};
return true;
}
catch (Exception e) when (e is FormatException or InvalidOperationException)
{
result = null;
return false;
}
}
/// <summary>
/// Parse excel row to Measure.
/// </summary>
public Measure ParseMeasure(IRow row)
{
var timeSpan = TimeSpan.Parse(row.GetStringCell(MeasureCells.Time));
return new Measure
{
Id = Guid.NewGuid(),
DateTime = DateTime.Parse(row.GetStringCell(MeasureCells.Date)).Add(timeSpan),
TemperatureCelsius = (decimal) row.GetNumericCell(MeasureCells.TemperatureCelsius),
AirHumidity = (byte) row.GetNumericCell(MeasureCells.AirHumidity),
DewPoint = (decimal) row.GetNumericCell(MeasureCells.DewPoint),
AtmospherePressure = (ushort) row.GetNumericCell(MeasureCells.AtmospherePressure),
WindSpeed = (byte?) row.GetNullableNumericCell(MeasureCells.WindSpeed),
CloudHeight = (ushort?) row.GetNullableNumericCell(MeasureCells.CloudHeight),
AtmosphericVisibility = (byte?) row.GetNullableNumericCell(MeasureCells.AtmosphericVisibility),
// CloudinessId = null,
// ConditionId = null,
};
}
/// <summary>
/// Parse excel row to set of WindDirection.
/// </summary>
public HashSet<WindDirection> ParseWindDirections(IRow row) =>
row
.GetStringCell(MeasureCells.WindDirection)
.Split(',')
.Distinct()
.Select(v =>
new WindDirection
{
Name = v,
})
.ToHashSet();
/// <summary>
/// Parse excel row to Cloudiness.
/// </summary>
public Cloudiness ParseCloudiness(IRow row) =>
new()
{
Value = (byte) row.GetNumericCell(MeasureCells.Cloudiness),
};
/// <summary>
/// Parse excel row to WeatherCondition.
/// </summary>
public WeatherCondition ParseWeatherCondition(IRow row) =>
new()
{
Name = row.GetStringCell(MeasureCells.WeatherCondition),
};
}
Raw excel data
Output
I tried to save already readed data in a variable and search for related items from there. But in this way we have more complicated code and O(n^2) complicity.
I have a task to sort a set of values in the DataTable. BUt the tricky part is that the values have special characters like '.' or '-' and negative values as well. The following picture is my current output:
the data are separated by ';' in the picture.
I am using the following code to sort the data.
DataTable myDataTable = new DataTable();
myDataTable.Columns.Add("SN", typeof(string));
string myValues = "";
if (!File.Exists("d:\\DUDBC-values.txt")) //DUDBC-values.txt
{
Console.WriteLine("No file found");
Console.ReadKey();
return;
}
StreamReader file = new StreamReader("d:\\DUDBC-values.txt");
string line;
while ((line = file.ReadLine()) != null)
{
myValues += line;
myValues += ";";
}
file.Close();
string[] myValuesArray = myValues.Split(';');
myValuesArray = myValuesArray.Take(myValuesArray.Count() - 1).ToArray();
foreach (string myValue in myValuesArray)
{
DataRow myRow = myDataTable.NewRow();
myRow["SN"] = myValue;
myDataTable.Rows.Add(myRow);
}
string beforeSort = string.Join(";", myDataTable.AsEnumerable().Select(x => x["SN"]));
Console.WriteLine("Before Sorting:");
Console.WriteLine();
Console.WriteLine(beforeSort);
Console.WriteLine();
IEnumerable<DataRow> sortedValues = myDataTable.AsEnumerable()
.OrderBy(x =>
{
string currentStringValue = x["SN"].ToString();
char[] SplitChar = new char[] { '.', '-' };
string[] currentStringValueArray = new string[1];
try
{
float val = float.Parse(currentStringValue);
currentStringValueArray[0] = currentStringValue;
}
catch {
currentStringValueArray = currentStringValue.Split(SplitChar);
}
string currentPart = "";
int currentPartNumeric = 0;
if (currentStringValueArray.Length > 1)
{
for (int i = 0; i < currentStringValueArray.Length; i++)
{
if (int.TryParse(currentStringValueArray[i], out currentPartNumeric))
{
if (i >= 1)
currentPart += ".";
currentPart += currentPartNumeric.ToString();
}
else
{
try
{
if (i >= 1)
currentPart += ".";
currentPart += (((int)(char.ToUpper(char.Parse(currentStringValueArray[i])))) - 64).ToString();
}
catch { }
}
}
return Convert.ToString(currentPart, CultureInfo.InvariantCulture);
}
else
return 0m.ToString();
});
string afterSort = string.Join(";", sortedValues.Select(x => x["SN"]));
Console.WriteLine("After Sorting:");
Console.WriteLine();
Console.WriteLine(afterSort);
//Copy to your existing datatable
myDataTable = sortedValues.CopyToDataTable();
Console.ReadKey();
I was expecting it to be like this:
-1
1.1.a.1
1.2.a.1
1.2.a.2
1.2.a.3
1.3.1
2.1.2
2.1a.1
2.1a.2
2.5
2.6.1
2.7.1
2.7.2
2.7.16
2.25a
2.25b
2.42.1
2.42.2
3.1.1
3.1.2
3.5.2
3.6a.1
3.6a.2
3.6b.2
5.1a.1
5.1a.2
5.1a.3
5.1b.1
5.1b.2
5.1b.6
6.3.1
6.3.2
6.3.3
6.3.4
6.3.5
6.5.1
6.5.2-C11
6.5.3-C12
17.06.01.b.i
17.06.02.b.i
17.06.02.b.vi
18.01.b
18.02.01.b.iii
1000
What am i doing wrong? Help needed please. I had also asked this type of question in this post until users kept putting different types of values.
It looks like you need to sort in what's called "Natural sort order".
There is a Windows API function, StrCmpLogicalW() that you can use to do such a comparison.
You can wrap this in a set of extension methods for sorting List<T> or arrays like so:
public static class NaturalSortExt
{
/// <summary>Sorts a list in "Natural sort order", i.e. "9" sorts before "10".</summary>
/// <typeparam name="T">The type of elements in the list to be sorted.</typeparam>
/// <param name="self">The list to be sorted.</param>
/// <param name="stringSelector">A projection to convert list elements to strings for comparision.</param>
public static void SortNatural<T>(this List<T> self, Func<T, string> stringSelector)
{
self.Sort((lhs, rhs) => StrCmpLogicalW(stringSelector(lhs), stringSelector(rhs)));
}
/// <summary>Sorts a list in "Natural sort order", i.e. "9" sorts before "10".</summary>
/// <param name="self">The list to be sorted.</param>
public static void SortNatural(this List<string> self)
{
self.Sort(StrCmpLogicalW);
}
/// <summary>Sorts an array in "Natural sort order", i.e. "9" sorts before "10".</summary>
/// <param name="self">The array to be sorted.</param>
public static void SortNatural(this string[] self)
{
Array.Sort(self, StrCmpLogicalW);
}
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
static extern int StrCmpLogicalW(string lhs, string rhs);
}
Then you can just sort your array (or List<T>) as demonstrated in the sample code below:
class Program
{
static void Main()
{
string[] test =
{
"3.1.2",
"1.2.a.1",
"1.2.a.2",
"1.3.1",
"2.1.2",
"2.1a.2",
"2.1a.1",
"-1",
"2.5",
"2.7.1",
"1.1.a.1",
"2.7.16",
"2.7.2",
"2.25a",
"2.6.1",
"5.1a.3",
"2.42.2",
"2.25b",
"2.42.1",
"3.6a.2",
"5.1b.1",
"3.1.1",
"3.5.2",
"3.6a.1",
"3.6b.2",
"5.1a.1",
"1.2.a.3",
"5.1b.2",
"5.1b.6",
"6.3.1",
"6.3.2",
"17.06.02.b.i",
"6.3.3",
"5.1a.2",
"6.3.4",
"6.3.5",
"6.5.1",
"1000",
"6.5.2-C11",
"6.5.3-C12",
"17.06.01.b.i",
"17.06.02.b.vi",
"18.01.b",
"18.02.01.b.iii"
};
string[] expected =
{
"-1",
"1.1.a.1",
"1.2.a.1",
"1.2.a.2",
"1.2.a.3",
"1.3.1",
"2.1.2",
"2.1a.1",
"2.1a.2",
"2.5",
"2.6.1",
"2.7.1",
"2.7.2",
"2.7.16",
"2.25a",
"2.25b",
"2.42.1",
"2.42.2",
"3.1.1",
"3.1.2",
"3.5.2",
"3.6a.1",
"3.6a.2",
"3.6b.2",
"5.1a.1",
"5.1a.2",
"5.1a.3",
"5.1b.1",
"5.1b.2",
"5.1b.6",
"6.3.1",
"6.3.2",
"6.3.3",
"6.3.4",
"6.3.5",
"6.5.1",
"6.5.2-C11",
"6.5.3-C12",
"17.06.01.b.i",
"17.06.02.b.i",
"17.06.02.b.vi",
"18.01.b",
"18.02.01.b.iii",
"1000"
};
test.SortNatural();
Debug.Assert(test.SequenceEqual(expected));
Console.WriteLine(string.Join("\n", test));
}
}
I have this in my text file:
000000000:Carrots:$1.99:214:03/11/2015:03/11/2016:$0.99
000000001:Bananas:$1.99:872:03/11/2015:03/11/2016:$0.99
000000002:Chocolate:$2.99:083:03/11/2015:03/11/2016:$1.99
000000003:Spaghetti:$3.99:376:03/11/2015:03/11/2016:$2.99
000000004:Tomato Sauce:$1.99:437:03/11/2015:03/11/2016:$0.99
000000005:Lettuce:$0.99:279:03/11/2015:03/11/2016:$0.99
000000006:Orange Juice:$2.99:398:03/11/2015:03/11/2016:$1.99
000000007:Potatoes:$2.99:792:03/11/2015:03/11/2016:$1.99
000000008:Celery:$0.99:973:03/11/2015:03/11/2016:$0.99
000000009:Onions:$1.99:763:03/11/2015:03/11/2016:$0.99
000000010:Chicken:$8.99:345:03/11/2015:03/11/2016:$7.99
000000010:Chicken:$8.99:345:03/11/2015:03/11/2016:$7.99
I need to get the value of each of the "quantity" values from the position in bold.
EDIT:
I want to also compare the values that I got and give an error if the quantity is low.
Solution with minimal memory consumption in case of large input data.
In additional: there are not processing of incorrect data in quantity column. To do this just replace int.Parse block;
This is several methods to process file data using LINQ expressions
internal static class MyExtensions
{
/// <exception cref="OutOfMemoryException">There is insufficient memory to allocate a buffer for the returned string. </exception>
/// <exception cref="IOException">An I/O error occurs. </exception>
/// <exception cref="ArgumentException"><paramref name="stream" /> does not support reading. </exception>
/// <exception cref="ArgumentNullException"><paramref name="stream" /> is null. </exception>
public static IEnumerable<string> EnumerateLines(this Stream stream)
{
using (var reader = new StreamReader(stream))
{
do
{
var line = reader.ReadLine();
if (line == null) break;
yield return line;
} while (true);
}
}
/// <exception cref="ArgumentNullException"><paramref name="line"/> is <see langword="null" />.</exception>
public static IEnumerable<string> ChunkLine(this string line)
{
if (line == null) throw new ArgumentNullException("line");
return line.Split(':');
}
/// <exception cref="ArgumentNullException"><paramref name="chuckedData"/> is <see langword="null" />.</exception>
/// <exception cref="ArgumentException">Index should be not negative value</exception>
public static string GetColumnData(this IEnumerable<string> chuckedData, int columnIndex)
{
if (chuckedData == null) throw new ArgumentNullException("chuckedData");
if (columnIndex < 0) throw new ArgumentException("Column index should be >= 0", "columnIndex");
return chuckedData.Skip(columnIndex).FirstOrDefault();
}
}
This is example of usage:
private void button1_Click(object sender, EventArgs e)
{
var values = EnumerateQuantityValues("largefile.txt");
// do whatever you need
}
private IEnumerable<int> EnumerateQuantityValues(string fileName)
{
const int columnIndex = 3;
using (var stream = File.OpenRead(fileName))
{
IEnumerable<int> enumerable = stream
.EnumerateLines()
.Select(x => x.ChunkLine().GetColumnData(columnIndex))
.Select(int.Parse);
foreach (var value in enumerable)
{
yield return value;
}
}
}
just consider if you are managed to get all these lines in string array or list.
you can apply the below code to get the collection of quantity as IEnumerable<string>.
var quantity = arr.Select(c =>
{
var temp = c.Split('$');
if (temp.Length > 1)
{
temp = temp[1].Split(':');
if (temp.Length > 1)
{
return temp[1];
}
}
return null;
}).Where(c => c != null);
UPDATE
Check the Fiddle.
https://dotnetfiddle.net/HqKdeI
you simply need to split the string
string data = #"000000000:Carrots:$1.99:214:03/11/2015:03/11/2016:$0.99
000000001:Bananas:$1.99:872:03/11/2015:03/11/2016:$0.99
000000002:Chocolate:$2.99:083:03/11/2015:03/11/2016:$1.99
000000003:Spaghetti:$3.99:376:03/11/2015:03/11/2016:$2.99
000000004:Tomato Sauce:$1.99:437:03/11/2015:03/11/2016:$0.99
000000005:Lettuce:$0.99:279:03/11/2015:03/11/2016:$0.99
000000006:Orange Juice:$2.99:398:03/11/2015:03/11/2016:$1.99
000000007:Potatoes:$2.99:792:03/11/2015:03/11/2016:$1.99
000000008:Celery:$0.99:973:03/11/2015:03/11/2016:$0.99
000000009:Onions:$1.99:763:03/11/2015:03/11/2016:$0.99
000000010:Chicken:$8.99:345:03/11/2015:03/11/2016:$7.99";
string[] rows = data.split(Environment.Newline.ToCharArray());
foreach(var row in rows)
{
string[] cols = row.Split(':');
var quantity = cols[3];
}
You can use String.Split to do this.
// Read all lines into an array
string[] lines = File.ReadAllLines(#"C:\path\to\your\file.txt");
// Loop through each one
foreach (string line in lines)
{
// Split into an array based on the : symbol
string[] split = line.Split(':');
// Get the column based on index
Console.WriteLine(split[3]);
}
Check out the example code below. The string you care about is named theValueYouWantInTheString.
char[] delimiterChar = { ':' };
string input = #"000000010:Chicken:$8.99:345:03/11/2015:03/11/2016:$7.99";
string[] values = input.Split(delimiterChar);
string theValueYouWantInTheString = values[3];
If you have a problem, use regular expression. Now you have two problems.
Here is a program that uses your input as a txt file. The function GetQuantity returns a list with int that contains the quantity. With this approach you can define more groups to extract information from each line.
namespace RegExptester
{
class Program
{
private static List<int> GetQuantity(string txtFile)
{
string tempLineValue;
Regex regex = new Regex(#"[0-9]*:[a-zA-Z]*:\$[0-9]*\.[0-9]*:([0-9]*).*", RegexOptions.Compiled);
List<int> retValue = new List<int>();
using (StreamReader inputReader = new StreamReader(txtFile))
{
while (null != (tempLineValue = inputReader.ReadLine()))
{
Match match = regex.Match(tempLineValue);
if (match.Success)
{
if(match.Groups.Count == 2)
{
int numberValue;
if (int.TryParse(match.Groups[1].Value, out numberValue))
retValue.Add(numberValue);
}
}
}
}
return retValue;
}
static void Main(string[] args)
{
var tmp = GetQuantity("c:\\tmp\\junk.txt");
}
}
}
Apparently from each line you want the part between the 3th and the 4th colon. Linq can do that for you:
using (var textReader = new StreamReader(fileName))
{
// read all text and divide into lines:
var allText = textReader.ReadToEnd();
var allLines = textReader.Split(new char[] {'\r','\n'}, StringSplitIoptions.RemoveEmptyEntries);
// split each line based on ':', and take the fourth element
var myValues = allLines.Select(line => line.Split(new char[] {':'})
.Skip(3)
.FirstOrDefault();
}
If you want less readability, of course you can concatenate these statements into one line.
I'm trying to convert String to ASCII code, so i use this function :
public List<string> PrimaryCode(string OrginalStr)
{
List<string> lstResult = new List<string>();
int lenOrginal = OrginalStr.Length;
string subOrginalStr;
byte[] AsciisubOrginalStr;
int AC;
for (int i = 0; i < lenOrginal; i++)
{
subOrginalStr = OrginalStr.Substring(i, 1);
AsciisubOrginalStr = Encoding.ASCII.GetBytes(subOrginalStr);
if (AsciisubOrginalStr[0] > 100)
{
AC = Convert.ToInt32(AsciisubOrginalStr[0]);
lstResult.Add((AC ).ToString());
}
else
{
AC = Convert.ToInt32(AsciisubOrginalStr[0]);
lstResult.Add((AC).ToString());
}
}
return lstResult;
}
The other part of my project i need to convert the ASCII code to original text as you can see i use this function :
public List<string> PrimaryCodeRev(List<string> CodedStr)
{
string res = "";
foreach (string s in CodedStr)
{
res = res+s;
}
List<string> lstResult = new List<string>();
int lenOrginal = res.Length;
string subOrginalStr;
byte[] AsciisubOrginalStr;
int AC;
for (int i = 0; i < lenOrginal; i++)
{
subOrginalStr = res.Substring(i, 1);
AsciisubOrginalStr = Encoding.ASCII.GetBytes(subOrginalStr);
if (AsciisubOrginalStr[0] < 100)
{
AC = Convert.ToInt32(AsciisubOrginalStr[0]);
lstResult.Add((AC).ToString());
}
else
{
AC = Convert.ToInt32(AsciisubOrginalStr[0]);
lstResult.Add((AC).ToString());
}
}
return lstResult;
}
The string input hello
convert to ascii result :
Convert ascii to main text :
But it doesn't work and it doesn't return the main text. Why ?
You seem to be making it too complicated...
If your input string only ever contains ASCII characters (which must be a requirement), then you can encode it as follows:
public static IEnumerable<string> ToDecimalAscii(string input)
{
return input.Select(c => ((int)c).ToString());
}
You can convert it back to a string like so:
public static string FromDecimalAscii(IEnumerable<string> input)
{
return new string(input.Select(s => (char)int.Parse(s)).ToArray());
}
Putting it together into a compilable console program:
using System;
using System.Collections.Generic;
using System.Linq;
namespace Demo
{
class Program
{
static void Main(string[] args)
{
string original = "hello";
var encoded = ToDecimalAscii(original);
Console.WriteLine("Encoded:");
Console.WriteLine(string.Join("\n", encoded));
Console.WriteLine("\nDecoded: " + FromDecimalAscii(encoded));
}
public static IEnumerable<string> ToDecimalAscii(string input)
{
return input.Select(c => ((int)c).ToString());
}
public static string FromDecimalAscii(IEnumerable<string> input)
{
return new string(input.Select(s => (char)int.Parse(s)).ToArray());
}
}
}
Let me reiterate: This will ONLY work if your input string is guaranteed to contain only characters that are in the ASCII set.
This does not really answer the question of why you want to do this. If you are trying to encode something, you might be better using some sort of encrypting method which outputs an array of bytes, and converting that array to base 64.
This does look like an X-Y question to me.
For getting Ascii code simply do as follows.
byte[] asciiBytes = Encoding.ASCII.GetBytes(value);
For string from AScii code,
char c1 = (char) asciiCode;
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
*/