2

I have a string which represents byte array, inside of it I have several groups of numbers (usually 5): which are encoded as 0x30..0x39 (codes for 0..9 digits). Before and after each number I have a space (0x20 code).

Examples:

"E5-20-32-36-20-E0"                // "32-36" encodes number "26", notice spaces: "20"
"E5-20-37-20-E9"                   // "37" encodes number "7"
"E5-20-38-20-E7-E4-20-37-35-20-E9" // two numbers: "8" (from "38") and "75" (from "37-35")

I want to find out all these groups and reverse digits in the encoded numbers:

   8 -> 8
  75 -> 57
 123 -> 321

Desired outcome:

"E5-20-32-36-20-E0"                   -> "E5-20-36-32-20-E0"
"E5-20-37-20-E9"                      -> "E5-20-37-20-E9"
"E5-20-37-38-39-20-E9"                -> "E5-20-39-38-37-20-E9" 
"E5-20-38-39-20-E7-E4-20-37-35-20-E9" -> "E5-20-39-38-20-E7-E4-20-35-37-20-E9"

I have the data inside a List \ String \ Byte[] - so maybe there is a way to do it ?

Thanks,

Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
David12123
  • 119
  • 4
  • 15

3 Answers3

2

It's unclear (from the original question) what do you want to do with the the digits; let's extract a custom method for you to implement it. As an example, I've implemented reverse:

32          -> 32
32-36       -> 36-32
36-32-37    -> 37-32-36
36-37-38-39 -> 39-38-37-36

Code:

// items: array of digits codes, e.g. {"36", "32", "37"}
//TODO: put desired transformation here
private static IEnumerable<string> Transform(string[] items) {
  // Either terse Linq:
  // return items.Reverse();

  // Or good old for loop:
  string[] result = new string[items.Length];

  for (int i = 0; i < items.Length; ++i)
    result[i] = items[items.Length - i - 1];

  return result;
}

Now we can use regular expressions (Regex) to extract all the digit sequencies and replace them with transformed ones:

  using System.Text.RegularExpressions;

  ...

  string input = "E5-20-36-32-37-20-E0";

  string result = Regex
    .Replace(input, 
           @"(?<=20\-)3[0-9](\-3[0-9])*(?=\-20)", 
             match => string.Join("-", Transform(match.Value.Split('-'))));

  Console.Write($"Before: {input}{Environment.NewLine}After:  {result}";);

Outcome:

Before: E5-20-36-32-37-20-E0
After:  E5-20-37-32-36-20-E0

Edit: In case reverse is the only desired transformation, the code can be simplified by dropping Transform and adding Linq:

using System.Linq;
using System.Text.RegularExpressions;

...

string input = "E5-20-36-32-37-20-E0";

string result = Regex
  .Replace(input, 
          @"(?<=20\-)3[0-9](\-3[0-9])*(?=\-20)", 
           match => string.Join("-", match.Value.Split('-').Reverse()));

More tests:

private static string MySolution(string input) {
  return Regex
    .Replace(input,
           @"(?<=20\-)3[0-9](\-3[0-9])*(?=\-20)",
             match => string.Join("-", Transform(match.Value.Split('-'))));
} 

...

string[] tests = new string[] {
  "E5-20-32-36-20-E0",
  "E5-20-37-20-E9",
  "E5-20-37-38-39-20-E9",
  "E5-20-38-39-20-E7-E4-20-37-35-20-E9",
};

string report = string.Join(Environment.NewLine, tests
  .Select(test => $"{test,-37} -> {MySolution(test)}"));

Console.Write(report);

Outcome:

E5-20-32-36-20-E0                     -> E5-20-36-32-20-E0
E5-20-37-20-E9                        -> E5-20-37-20-E9
E5-20-37-38-39-20-E9                  -> E5-20-39-38-37-20-E9
E5-20-38-39-20-E7-E4-20-37-35-20-E9   -> E5-20-39-38-20-E7-E4-20-35-37-20-E9

Edit 2: Regex explanation (see https://www.regular-expressions.info/lookaround.html for details):

   (?<=20\-)         - must appear before the match: "20-" ("-" escaped with "\")
   3[0-9](\-3[0-9])* - match itself (what we are replacing in Regex.Replace) 
   (?=\-20)          - must appear after the match "-20" ("-" escaped with "\")

Let's have a look at match part 3[0-9](\-3[0-9])*:

   3           - just "3"
   [0-9]       - character (digit) within 0-9 range
   (\-3[0-9])* - followed by zero or more - "*" - groups of "-3[0-9]"
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • Pretty good, but it seems he wants full inversion on number indexes. anyway I was working on the regex you just put ^^. @David12123: when in need to test a regex, I love the share this (it may help you): https://regex101.com/ – Mikitori Sep 25 '18 at 09:59
  • I'm sorry - but i can;t seem to understand what i don't explain good - I want to find the numbers in my string array (which is in Hex) and reverse it's order : 12-21,123-321,1234-4321,55-55,1719-9171 – David12123 Sep 25 '18 at 10:02
  • 1
    @Mikitori: Now (with *two digits swapped* in the question's only example) we can only guess what the actual transformation should be. That is the very reason I've extracted `Transform` method – Dmitry Bychenko Sep 25 '18 at 10:03
  • @David12123: OK, I see; let's edit `Transform` method – Dmitry Bychenko Sep 25 '18 at 10:07
  • @DmitryBychenko I agree, my guess was based on previous comments (and i still upvoted your answer ;) ). for reversing char, i like the code posted here: https://stackoverflow.com/questions/228038/best-way-to-reverse-a-string too bad it doesn't really fits here ^^ – Mikitori Sep 25 '18 at 10:09
  • @Mikitori: we are reversing *array*; technically, we can do it with a help of *Linq*: return `items.Reverse();` – Dmitry Bychenko Sep 25 '18 at 10:12
  • @DmitryBychenko, yep, I really need to achieve the linq reflexe, I'm from C++ at the origin, and I'm going to C# now, so having everything ready is quite new for me ^^ – Mikitori Sep 25 '18 at 10:30
  • this one is working , Thanks ! can you explain to me how does it works? so I will know for the next time? – David12123 Sep 25 '18 at 10:47
  • 1
    @David12123: you are welcome! Next time, please, spend few minutes more to put a question :) – Dmitry Bychenko Sep 25 '18 at 10:55
1

I'm not sure but I guess the length can change and you just want to reorder in reverse order just the numbers. so a possible way is:

  • Put the string in 2 arrays (so they are the same)
  • Iterate through one of them to locate begin and end o fthe number area
  • Go from end-area to begin-area in first array and write to the second from begin-area to end-area

Edit: not really tested, i just wrote that quickly:

    string input = "E5-20-36-32-37-20-E0";
    string[] array1 = input.Split('-');
    string[] array2 = input.Split('-');

    int startIndex = -1;
    int endIndex = -1;

    for (int i= 0; i < array1.Length; ++i)
    {
        if (array1[i] == "20")
        {
            if (startIndex < 0)
            {
                startIndex = i + 1;
            }
            else
            {
                endIndex = i - 1;
            }
        }
    }

    int pos1 = startIndex;
    int pos2 = endIndex;
    for (int j=0; j < (endIndex- startIndex + 1); ++j)
    {
        array1[pos1] = array2[pos2];
        pos1++;
        pos2--;
    }
Mikitori
  • 589
  • 9
  • 21
  • this is what I want , and thought to do - but how to do it? – David12123 Sep 25 '18 at 09:25
  • @David12123 just a minute i will type something, but the description is pretty self-explanatory, you should try ^^ – Mikitori Sep 25 '18 at 09:26
  • all this time I have tried - this is why I have ask here :-) – David12123 Sep 25 '18 at 09:27
  • i edited the answer, probably not the most elegant way to do it, but now improving the code is your job, you have the idea ^^ – Mikitori Sep 25 '18 at 09:39
  • My answer consider only one number area but its size doesn' matter. I put no check at all, be careful when playing with index of an array, going too far is pretty easy, you should add some protections – Mikitori Sep 25 '18 at 09:40
  • I can try working on it - but not all the time after a 0x20 there will be a number could be something else - this is why I'm looking to do an if with this condition: 0x20&0x30-0x39 – David12123 Sep 25 '18 at 09:42
  • Mmm ok, I missed this part, in such a case, combining with regex should help, If I have time I will post a more complete answer – Mikitori Sep 25 '18 at 09:45
0

If you would be clear about how you want to process the numbers, it would be easier to provide a solution.

  • Do you want to swap them randomly?
  • Do you want to reverse order?
  • Do you want to swap every second number with the number before?
  • Do you want to swap ...

you can try the following (for reversing the numbers)

string hex = "E5-20-36-32-20-E0"; // this is your input string

// split the numbers by '-' and generate list out of it
List<string> hexNumbers = new List<string>();
hexNumbers.AddRange(hex.Split('-'));

// find start and end of the numbers that should be swapped
int startIndex = hexNumbers.IndexOf("20");
int endIndex = hexNumbers.LastIndexOf("20");

string newHex = "";
// add the part in front of the numbers that should be reversed
for (int i = 0; i <= startIndex; i++) newHex += hexNumbers[i] + "-";
// reverse the numbers
for (int i = endIndex-1; i > startIndex; i--) newHex += hexNumbers[i] + "-";
// add the part behind the numbers that should be reversed
for (int i = endIndex; i < hexNumbers.Count-1; i++) newHex += hexNumbers[i] + "-";
newHex += hexNumbers.Last();

If the start and the end is always the same, this can be fairly simplified into 4 lines of code:

string[] hexNumbers = hex.Split('-');
string newHex = "E5-20-";
for (int i = hexNumbers.Count() - 3; i > 1; i--) newHex += hexNumbers[i] + "-";
newHex += "20-E0";

Results:

"E5-20-36-32-20-E0" -> "E5-20-32-36-20-E0"
"E5-20-36-32-37-20-E0"    -> "E5-20-32-37-36-20-E0"
"E5-20-36-12-18-32-20-E0" -> "E5-20-32-18-12-36-20-E0"
julian bechtold
  • 1,875
  • 2
  • 19
  • 49
  • first time use of Regex , so please explain (if you can) - also I get this error: Severity Code Description Project File Line Suppression State Error CS0019 Operator '&&' cannot be applied to operands of type 'Match' and 'bool' ReadSerailData – David12123 Sep 25 '18 at 09:35
  • I want to swap the order,not random - so when I find 0x39,0x34 -- I want to change it to :0x34,0x39. and if I have 0x36,0x37,0x31 - it will be 0x31,0x37,0x36 – David12123 Sep 25 '18 at 09:37
  • sorry @david my code was totally untested - this code should now work as of your request. Regex (regular expressions) are a speciall format to match strings. for example [0-9] matches any number between 0-9. [0-9]+ matcvhes any number from 0 - infinite. definitely worth a look – julian bechtold Sep 25 '18 at 09:54