locked
Very difficult string manipulate RRS feed

  • Question

  • User-2146352328 posted

    Hi.
    I am getting a string of seats that looks like this:
    "1|11|25|1|1|0000000001|0|0|Y|Main||9|10|A|2002020N01903020M01804020L01706020J01607020I01508020H0140 9020G0130A020F0120B020E0110C020D0100D020C090E020B080F020A070G0209060H0208050I0207040K0205030L0204020 M0203010N02020|9|B|2002030N01903030M01804030L01706030J01607030I01508030H01409030G0130A030F0120B030E0 110C030D0100D030C090E030B080F030A070G0309060H0308050I0307040K0305030L0304020M03030|8|C|2101040O02002 040N01903040M01804040L01706040J01607040I01508040H01409040G0130A040F0120B040E0110C040D0100D040C090E04 0B080F040A070G0409060H0408050I0407040K0405030L0404020M0403010N04020|7|D|2101050O02002050N01903050M01 804050L01706050J01607050I01508050H01409050G0130A050F0120B050E0110C050D0100D050C090E050B080F050A070G0 509060H0508050I0507040K0505030L0504020M0503010N05020|6|E|2101060O02002060N01903060M01804060L01706060 J01607060I01508060H01409060G0130A060F0120B060E0110C060D0100D060C090E060B080F060A070G0609060H0608050I 0607040K0605030L0604020M0603010N06020|5|F|2101070O02002070N01903070M01804070L01706070J01607070I01508 070H01409070G0130A070F0120B070E0110C070D0100D070C090E070B080F070A070G0709060H0708050I0707040K0705030 L0704020M0703010N07020|4|G|2101080O02002080N01903080M01804080L01706080J01607080I01508080H01409080G01 30A080F0120B080E0110C080D0100D080C090E080B080F080A070G0809060H0808050I0807040K0805030L0804020M080301 0N08020|3|H|2101090O02002090N01903090M01804090L01706090J01607090I01508090H11409090G1130A090F5120B090 E5110C090D0100D090C090E090B080F090A070G0909060H0908050I0907040K0905130L0904120M0903110N09021|2|J|210 10A0O020020A0N019030A0M018040A0L016070A0I115080A0H114090A0G1130A0A0F1120B0A0E0110C0A0D0100D0A0C090E0 A0B080F0A0A070G0A09060H0A08040K0A05030L0A04020M0A03010N0A020"

    You will see that after Main||9|10|A|. So Starting, let's take a little sample after |A| . "2002020N01903020M01804020L01706020J0" .Analyzing this we get:
    2chars for the seat number(20),2char for the seat allocationNum(02), 2char + 2char for the XY position( 02 + 0N) + 1 char for status (0).
    So the first bunch would be "2002020N0", the second "1903020M0" etc. There was an older version that did not include the seat and had 7 chars so i divided by 7 to get the total seats of the row. Now i supposedly will divide by 9 as we have 9 chars per session. Now starts the trouble. If you look after the 10 seat the problem is that the 9th seat is not represented by 09 but with 9, hence I character. Are you starting to see the stupidity of the situation? "90E020B080F020A0" It gets 8 characters!!! So everything is messed up. If i try to get the seat number I will get 90 and 80 instead of what they supposed to do (09,08) so I can get 08 and 09, also since there is characters missing the division will fail badly.
    What I want to do, if possible is insert the missing data. So 9 will be 09, to will be 08 etc. The problem is that it's not unique, meaning 9 -09 appears everywhere in the string, and this is not a default string. It may start with 8 seats so it won't be , first seat 20 2nd seat 19 etc.
    I literal don't have a clue on what I can do. How can i "sneak" the zeros in from of the single characters so I can make the string correct?
    Any help would be appreciated.
    This is a .net 2.0 framework

    Thursday, April 30, 2015 10:58 AM

Answers

  • User-1910946339 posted

    I created a class to hold the information about one seat and to populate itself with information from a string

    class SeatInfo {
    	public int Number {get; private set;}
    	public string Allocation {get; private set;}
    	public string X {get; private set;}
    	public string Y {get; private set;}
    	public char Status {get;private set;}
    
    	public SeatInfo(int number) {
    		this.Number = number;
    	}
    	
    	public int Fill(string inChars) {
    		int start = Number < 10 ? 1 : 2;
    		
    		if (inChars.Length < start + 7) return -1;
    		
    		this.Allocation = inChars.Substring(start, 2);
    		this.X = inChars.Substring(start+2, 2);
    		this.Y = inChars.Substring(start+4, 2);
    		this.Status = inChars[start+6];
    		
    		return start + 7;
    	}
    }

    This class relies on being told what the seat number is to correctly extract information from the string.

    void Main()
    {
    	var input = "1|11|25|1|1|0000000001|0|0|Y|Main||9|10|A|2002020N01903020M01804020L01706020J01607020I01508020H01409020G0130A020F0120B020E0110C020D0100D020C090E020B080F020A070G0209060H0208050I0207040K0205030L0204020M0203010N02020|9|B|2002030N01903030M01804030L01706030J01607030I01508030H01409030G0130A030F0120B030E0110C030D0100D030C090E030B080F030A070G0309060H0308050I0307040K0305030L0304020M03030|8|C|2101040O02002040N01903040M01804040L01706040J01607040I01508040H01409040G0130A040F0120B040E0110C040D0100D040C090E040B080F040A070G0409060H0408050I0407040K0405030L0404020M0403010N04020|7|D|2101050O02002050N01903050M01804050L01706050J01607050I01508050H01409050G0130A050F0120B050E0110C050D0100D050C090E050B080F050A070G0509060H0508050I0507040K0505030L0504020M0503010N05020|6|E|2101060O02002060N01903060M01804060L01706060J01607060I01508060H01409060G0130A060F0120B060E0110C060D0100D060C090E060B080F060A070G0609060H0608050I0607040K0605030L0604020M0603010N06020|5|F|2101070O02002070N01903070M01804070L01706070J01607070I01508070H01409070G0130A070F0120B070E0110C070D0100D070C090E070B080F070A070G0709060H0708050I0707040K0705030L0704020M0703010N07020|4|G|2101080O02002080N01903080M01804080L01706080J01607080I01508080H01409080G0130A080F0120B080E0110C080D0100D080C090E080B080F080A070G0809060H0808050I0807040K0805030L0804020M0803010N08020|3|H|2101090O02002090N01903090M01804090L01706090J01607090I01508090H11409090G1130A090F5120B090E5110C090D0100D090C090E090B080F090A070G0909060H0908050I0907040K0905130L0904120M0903110N09021|2|J|21010A0O020020A0N019030A0M018040A0L016070A0I115080A0H114090A0G1130A0A0F1120B0A0E0110C0A0D0100D0A0C090E0A0B080F0A0A070G0A09060H0A08040K0A05030L0A04020M0A03010N0A020";
    	var inputPieces = input.Split("|".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
    	int piece = 0;
    	int pieceCount = inputPieces.Length;
    	
    	// Find the 'Main' piece
    	while (piece < pieceCount && inputPieces[piece++] != "Main")
    	{ }
    	
    	piece += 3; // Skip over the |9|10|A|
    	
    	var allSeats = new List<List<SeatInfo>>();
    	while (piece < pieceCount) {
    		inputPieces[piece].Dump();
    		var firstSeatNumber = int.Parse(inputPieces[piece].Substring(0,2));
    		int pieceOffset = 0;
    		
    		var seatGroup = new List<SeatInfo>();
    		for (int seatNumber = firstSeatNumber; seatNumber > 0; seatNumber--)
    		{
    			var seat = new SeatInfo(seatNumber);
    			var seatLength = seat.Fill(inputPieces[piece].Substring(pieceOffset));
    			if (seatLength > 0) {
    				pieceOffset += seatLength;
    				seatGroup.Add(seat);
    			} else {
    				seatNumber = 0;
    			}
    		}
    		
    		allSeats.Add(seatGroup);
    		
    		piece += 3;
    	}
    	
    	allSeats.Dump();	
    }

    First split the input on the '|' character to get what I call the 'pieces' of the input.

    Then skip over the header information until you get to a 'piece' which is the string "Main"

    Then skip 3 pieces to get to the first group of seats.  (you probably need to do something with the header stuff but I just ignore it)

    Now I assume that the next two characters give me the number of the first seat, that is that the first seat in a group is always a two digit seat number..  The seat number is found using the int.Parse method.  If the first seat is 33 then the next seat is 32 and then 31 and so on.  The SeatInfo.Fill method uses the seat number which we are keeping track of to work out where the individual fields are in the string.

    This code needs a lot of error checking added to make it more robust.  And I don't like that Fill returns an int, but what do you want for free?

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, May 8, 2015 2:09 AM

All replies

  • User-2146352328 posted

    can't quite figure how to predict the 8 to 9 chars.I am not sure.
    This is what I am trying:

    originalRowSubStr = seatsData;
    
                SeatGridRowId = Convert.ToInt32(seatgridrowid);
                RowPhysId = rowphysId;
    // this goes our wrong as the length has been altered due to less characters used than expected (when seats go below number 10)
                int seatsnum = seatsData.Length / 9; /// 8;
    // for now i just put a +1 to have the correct loop but this is a hack, will not work with more or less length, I just luckily matched here
                seatsnum += 1;                                  
                //int seatsnum = seatsData.Length / 7; /// 8;
                String[] seatdata = new String[seatsnum];
                seats = new Seat[seatsnum];
    
    
    //seatdata being on row of data that is determined elsewhere( that is correct so I do not put it here)
      maxX = 0;
                for (int i = 0; i < seatsnum; i++){
                    //used for mapping screen details with Vista data
                    seats[i] = new Seat(seatsData.Substring(i * 9, 9), i + 1, RowPhysId, seatsnum); 
               //     new Seat(seatsData.Substring(i * 8, 8), i+1, RowPhysId, seatsnum);
                 //    String sd = seatsData.Substring(i * 8, 8);
                    String sd = seatsData.Substring(i * 9, 9);
    
                    if (maxX < seats[i].Xposition) {
                        maxX = seats[i].Xposition;                
                    }
                }

    //seat function

     public Seat(String data, int rowindex, String rowname, int seatsNumInRow) {
                
                originalSeatData = data;
                
                rowIndex = rowindex;
                rowName = rowname;
    
    //everyting start to mess up when the 2char becomes 1 char...
           //     VistaGridSeat = data.Substring(0, 2);
             //   VistaYpos = data.Substring(2, 2);
               // VistaXpos = data.Substring(4, 2);
                VistaGridSeat = data.Substring(2, 2);
                   VistaYpos = data.Substring(4, 2);
                 VistaXpos = data.Substring(6, 2);
                 string vt = data.Substring(0, 2);
                for (int i = 0; i < VistaCoords.Length; i++) {
    //vistacords = a board with charr2 length that match // can provide if needed but is not the crucial think here
                    if (VistaYpos == VistaCoords[i]) {
                        Ypos = i;
                        break;
                    }
                }
                
    
                for (int i = 0; i < VistaCoords.Length; i++)
                {
                    if (VistaXpos == VistaCoords[i])
                    {
                        Xpos = i;
                        break;
                    }
                }
    
                for (int i = 0; i < VistaCoords.Length; i++)
                {
                    if (VistaGridSeat == VistaCoords[i])
                    {
                        GridSeatNum = i;
                        break;
                    }
                }
                seatLabel = Convert.ToString(seatsNumInRow - (GridSeatNum - 1) + Xpos);
                //Console.WriteLine("Seat label:" + rowName + seatLabel + "  [ (" + seatsNumInRow +"-("+GridSeatNum+"-1)+"+Xpos+") ]");
    
                //Ypos = (VistaCoords.LastIndexOf("|" + VistaYpos + "|"));
                //Xpos = (VistaCoords.LastIndexOf("|"+VistaXpos+"|"));
    
                //Console.WriteLine(data +"=>"+Ypos + "-" +Xpos);
    
                //Ypos = Convert.ToInt32(data.Substring(2, 2));
                //Xpos = Convert.ToInt32(data.Substring(4, 2));
                status = Convert.ToInt32(data.Substring(6, 1));
                //priority = Convert.ToInt32(data.Substring(7, 1));

    Thursday, April 30, 2015 10:59 AM
  • User-1078840699 posted

    You can use Substring:

    myString.Substring(0,3)
    myString.Substring(3,2)
    myString.Substring(5,4)

    It's also possible to make it more complicated than necessary by using a combination of regular expressions and LINQ:

    string myString = "123987898";
    Regex regex = new Regex("(.{3})(.{2})(.{4})");
    string[] bits = regex
        .Match(myString)
        .Groups
        .Cast<Group>()
        .Skip(1)
        .Select(match => match.Value)
        .ToArray();

    Also, do check this link 

    and 

    http://www.csharptuts.net/string-manipulation-functions-in-c/

    Saturday, May 2, 2015 2:28 PM
  • User-2146352328 posted

    I am using substring already.

    The problem is that after the values go from 12, 11, 10 to 9,8,7 the substring picks up the wrong values.

    Monday, May 4, 2015 4:32 AM
  • User-1910946339 posted

    I created a class to hold the information about one seat and to populate itself with information from a string

    class SeatInfo {
    	public int Number {get; private set;}
    	public string Allocation {get; private set;}
    	public string X {get; private set;}
    	public string Y {get; private set;}
    	public char Status {get;private set;}
    
    	public SeatInfo(int number) {
    		this.Number = number;
    	}
    	
    	public int Fill(string inChars) {
    		int start = Number < 10 ? 1 : 2;
    		
    		if (inChars.Length < start + 7) return -1;
    		
    		this.Allocation = inChars.Substring(start, 2);
    		this.X = inChars.Substring(start+2, 2);
    		this.Y = inChars.Substring(start+4, 2);
    		this.Status = inChars[start+6];
    		
    		return start + 7;
    	}
    }

    This class relies on being told what the seat number is to correctly extract information from the string.

    void Main()
    {
    	var input = "1|11|25|1|1|0000000001|0|0|Y|Main||9|10|A|2002020N01903020M01804020L01706020J01607020I01508020H01409020G0130A020F0120B020E0110C020D0100D020C090E020B080F020A070G0209060H0208050I0207040K0205030L0204020M0203010N02020|9|B|2002030N01903030M01804030L01706030J01607030I01508030H01409030G0130A030F0120B030E0110C030D0100D030C090E030B080F030A070G0309060H0308050I0307040K0305030L0304020M03030|8|C|2101040O02002040N01903040M01804040L01706040J01607040I01508040H01409040G0130A040F0120B040E0110C040D0100D040C090E040B080F040A070G0409060H0408050I0407040K0405030L0404020M0403010N04020|7|D|2101050O02002050N01903050M01804050L01706050J01607050I01508050H01409050G0130A050F0120B050E0110C050D0100D050C090E050B080F050A070G0509060H0508050I0507040K0505030L0504020M0503010N05020|6|E|2101060O02002060N01903060M01804060L01706060J01607060I01508060H01409060G0130A060F0120B060E0110C060D0100D060C090E060B080F060A070G0609060H0608050I0607040K0605030L0604020M0603010N06020|5|F|2101070O02002070N01903070M01804070L01706070J01607070I01508070H01409070G0130A070F0120B070E0110C070D0100D070C090E070B080F070A070G0709060H0708050I0707040K0705030L0704020M0703010N07020|4|G|2101080O02002080N01903080M01804080L01706080J01607080I01508080H01409080G0130A080F0120B080E0110C080D0100D080C090E080B080F080A070G0809060H0808050I0807040K0805030L0804020M0803010N08020|3|H|2101090O02002090N01903090M01804090L01706090J01607090I01508090H11409090G1130A090F5120B090E5110C090D0100D090C090E090B080F090A070G0909060H0908050I0907040K0905130L0904120M0903110N09021|2|J|21010A0O020020A0N019030A0M018040A0L016070A0I115080A0H114090A0G1130A0A0F1120B0A0E0110C0A0D0100D0A0C090E0A0B080F0A0A070G0A09060H0A08040K0A05030L0A04020M0A03010N0A020";
    	var inputPieces = input.Split("|".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
    	int piece = 0;
    	int pieceCount = inputPieces.Length;
    	
    	// Find the 'Main' piece
    	while (piece < pieceCount && inputPieces[piece++] != "Main")
    	{ }
    	
    	piece += 3; // Skip over the |9|10|A|
    	
    	var allSeats = new List<List<SeatInfo>>();
    	while (piece < pieceCount) {
    		inputPieces[piece].Dump();
    		var firstSeatNumber = int.Parse(inputPieces[piece].Substring(0,2));
    		int pieceOffset = 0;
    		
    		var seatGroup = new List<SeatInfo>();
    		for (int seatNumber = firstSeatNumber; seatNumber > 0; seatNumber--)
    		{
    			var seat = new SeatInfo(seatNumber);
    			var seatLength = seat.Fill(inputPieces[piece].Substring(pieceOffset));
    			if (seatLength > 0) {
    				pieceOffset += seatLength;
    				seatGroup.Add(seat);
    			} else {
    				seatNumber = 0;
    			}
    		}
    		
    		allSeats.Add(seatGroup);
    		
    		piece += 3;
    	}
    	
    	allSeats.Dump();	
    }

    First split the input on the '|' character to get what I call the 'pieces' of the input.

    Then skip over the header information until you get to a 'piece' which is the string "Main"

    Then skip 3 pieces to get to the first group of seats.  (you probably need to do something with the header stuff but I just ignore it)

    Now I assume that the next two characters give me the number of the first seat, that is that the first seat in a group is always a two digit seat number..  The seat number is found using the int.Parse method.  If the first seat is 33 then the next seat is 32 and then 31 and so on.  The SeatInfo.Fill method uses the seat number which we are keeping track of to work out where the individual fields are in the string.

    This code needs a lot of error checking added to make it more robust.  And I don't like that Fill returns an int, but what do you want for free?

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, May 8, 2015 2:09 AM
  • User-2146352328 posted

    Hi.

    Thank you.

    Some notes. I cannot find a .dump function here(?) also "Main" is not always the case, the name can differ.

    Thanks.

    Friday, May 8, 2015 3:18 AM
  • User-1910946339 posted

    Dump is a utility function provided by LinqPad.net  it is not relevant to the solution.

    I really hope you can work out how to make "Main" a variable.

    Friday, May 8, 2015 3:57 AM
  • User-2146352328 posted

    Ok will see what I can do.

    Thanks.

    Friday, May 8, 2015 4:16 PM