2016-09-21 3 views
1

Я новичок в C# и не очень разбираюсь в строковых манипуляциях. У меня есть строка, которая представляет положение объекта на диаграмме. Строка содержит целочисленные значения, которые я хочу изменить для каждого объекта.изменить строку в C#

Пример

String Position = "l=50; r=190; t=-430; b=-480"; 

Я хочу изменить эту строку

String Position = "l=50; r=190; t=-505; b=-555"; 

Так что, если вы заметили, т = -430 изменяется на Т = -505 и Ь = -480 б = - 555, что означает приращение -75 как сверху, так и снизу

Как это сделать?

Благодаря

+10

Вы должны разобрать строку в объект, изменить значения и переформатировать строку. –

+0

Можете ли вы изменить источник строки? – BWA

+12

О, c'mon люди. Вопрос не так уж плох для новичков . Не заслуживает всех downvotes! – trailmax

ответ

0

Чтобы обеспечить дополнительное объяснение Jeroen van Langen «s комментарий

Вы должны Разбираем строка в объект, изменить значения и переформатировать строку.

Вы можете добиться этого с подобной установкой к этому:

public class Position 
{ 
    public int l { get; set; } 
    public int r { get; set; } 
    public int t { get; set; } 
    public int b { get; set; } 

    public override string ToString() 
    { 
     return $"l = {l}, r = {r}, t = {t}, b = {b}"; 
    } 
} 

(изменить модификаторы доступа в соответствии с вашими потребностями)

И работать с объектом (просто), как показано ниже:

public void UpdatePostion() 
    { 
     // Create new position 
     Position pos = new Position 
     { 
      l = 50, 
      r = 190, 
      t = -430, 
      b = -480 
     }; 
     Console.WriteLine($"Pos before change: {pos.ToString()}"); 

     // change top and bottom value to accommodate increment 
     pos.t += -75; 
     pos.b += -75; 

     // Prove that they've been updated 
     Console.WriteLine($"Pos after change: {pos.ToString()}"); 
    } 
4

Если вы хотите, чтобы легко заполнить или изменить значение во входной строке, вы можете использовать string.Format(), как это:

Position = string.Format("l={0}; r={1}; t={2}; b={3}", 50, 190, -430, -480); 

Вы можете извлечь значение существующей строки ввода с помощью регулярные выражения, как это:

String Position = "l=50; r=190; t=-430; b=-480"; 
string pattern = @"^l=(\-{0,1}\d+); r=(\-{0,1}\d+); t=(\-{0,1}\d+); b=(\-{0,1}\d+)$"; 
var captGroups = Regex.Match(Position, pattern).Groups; 
var l = captGroups[1]; 
var r = captGroups[2]; 
var t = captGroups[3]; 
var b = captGroups[4]; 
+4

Нет, это пропускает шаг разбора строки в первую очередь. – CodeCaster

+0

@CodeCaster - этот вопрос не о том, как получить значения из строки, это о том, как изменить строку с новыми значениями. "Строка содержит целочисленные значения, которые Я хочу изменить для каждого объекта. » –

+6

Да, и как ваш ответ показывает это? Ваш ответ предполагает, что OP имеет номера в первую очередь, в то время как вопрос предполагает, что ввод представляет собой строку, содержащую номер. – CodeCaster

1
String Position = "l=50; r=190; t=-430; b=-480"; 
    public void modifyPosition(int l, int r, int t, int b) 
    { 
    string[] parts = Position.Split(';'); 
    int oldL = int.Parse(parts[0].Replace("l=","").Trim()); 
    int oldR = int.Parse(parts[1].Replace("r=","").Trim()); 
    int oldT = int.Parse(parts[2].Replace("t=","").Trim()); 
    int oldB = int.Parse(parts[3].Replace("b=","").Trim()); 
    Position = "l="+(oldL+l).ToString()+"; r="+(oldR+r).ToString()+ 
    "; t="+(oldT+t).ToString()+"; b="+(oldB+b).ToString()+";"; 
    } 

Там есть много способов обобщить и оптимизировать это - я оставлю их до вас ...

2

Вам нужно разобрать свое выражение. Вот пример, в котором строка первого расщепляется для ;, а затем каждая часть расщепляется =:

var position = "l=50; r=190; t=-430; b=-480"; 
var parts = position.Split(';'); // split string into 4 parts 
var assignments = new Dictionary<string, int>(); 

foreach (var part in parts) 
{ 
    var trimmedPart = part.Trim(); 
    var assignmentParts = trimmedPart.Split('='); // split each part into variable and value part 
    var value = Int32.Parse(assignmentParts[1]); // convert string to integer value 
    assignments.Add(assignmentParts[0], value); 
} 

// change values 
assignments["t"] = -505; 
assignments["b"] = -555; 

// build new string 
var newPosition = String.Join("; ", assignments.Select(p => p.Key + "=" + p.Value)); 
Console.WriteLine(">> " + newPosition); 
+0

думал по той же линии, но если позиция дублируется, то не уверен, как она будет себя вести. – Rahul

+1

Похоже, что определение прямоугольника - левое, правое, верхнее, нижнее - поэтому, по-видимому, каждое значение будет уникальным. – FacticiusVir

0

Таким образом, основываясь на одном из предложений комментариев о разборе объектов, вы можете представить свой объект Position следующим образом s:

public class Position 
{ 
    public int Left { get; set; } 
    public int Right { get; set; } 
    public int Top { get; set; } 
    public int Bottom { get; set; } 
    public Position(string str) 
    { 
     int[] values = str.Split(new[] { "; " }, StringSplitOptions.None) 
      .Select(s => Convert.ToInt32(s.Substring(s.IndexOf('=') +1))).ToArray(); 
     Left = values[0]; 
     Right = values[1]; 
     Top = values[2]; 
     Bottom = values[3]; 
    } 

    public override string ToString() 
    { 
     return string.Join("; ", Left, Right, Top, Bottom); 
    } 
} 

Вы могли бы использовать этот объект для сериализации/десериализации вашей строки и от объекта следующим образом:

string intputString = "l=50; r=190; t=-430; b=-480"; 
Position p = new Position(intputString); 
p.Top -= 75; 
p.Bottom -= 75; 
string outputString = p.ToString();` 

Единственное, в любой реальной сложности превращает вашу строку в объект значения. Для этого мы можем разграничить строку на каждое отдельное значение, разделив строку на «;».Каждое значение затем может быть преобразовано в целое число, взяв подстроку каждого элемента после символа равенства («l = 50» станет «50») и преобразует его в целое.

0

Обычно вы не хотите манипулировать данными в строковой форме, если только данные не являются строкой. В этом случае у вас действительно есть структура, которая представляется в виде строки, поэтому сначала вы должны превратить ее в структуру.

Основанный на строках, которые вы предоставили, это превращает любую строку подобной формы в словарь.

var source = "l=50; r=190; t=-505; b=-555"; 
var components = source.Split(';').Select(x => x.Trim()); 
// components is now an enumerable of strings "l=50", "r=190" etc. 
var pairs = components.Select(x => x.Split('=').ToArray()); 
// pairs is now an enumerable of arrays of strings ["l", "50"], ["r", "190"] etc; 
var dictionary = pairs.ToDictionary(x => x[0], x => x[1]); 
// dictionary now contains r => 190, l => 50 etc. 

Конечно, вы хотите играть с реальными цифрами, так что вы хотите, чтобы преобразовать значения в целых действительно, так подкачки, что последняя строка из:

var dictionary = pairs.ToDictionary(x => x[0], x => Convert.ToInt32(x[1])); 

Теперь у вас есть словарь, который вам могут манипулировать:

dictionary["t"] = dictionary["t"] - 75; 

Например. Или вы можете использовать это как основу для заполнения объекта соответствующими свойствами и манипулирования ими.

struct Position { 
    public int L { get; set; } 
    public int R { get; set; } 
    public int T { get; set; } 
    public int B { get; set; } 
} 

Конечно, вы можете изменить его обратно в строку, когда вы закончите манипулировать им:

var newString = string.Join("; ", dictionary.Select(x => $"{x.Key}={x.Value}")); 

Хотя, если вы планируете работать с ним много, вы должны держать разобранный версии вокруг как можно дольше, так как цикл синтаксического анализа/рендеринга может быть проблемой производительности, если вы его много делаете.

Всегда храните ваши данные в соответствующих типах. Напишите новые классы, напишите новые структуры, они не должны быть сложными, но чем больше вы можете дать имена и формы вашим данным, тем легче манипулировать ими и обеспечить правильное управление им.

Это все очень упрощенно, конечно - нет обработки ошибок, например, если значение часть не является допустимым Int32 (Convert.ToInt32 будет сгенерировано исключение), или если есть повторяющиеся ключи (ToDictionary сгенерирует исключение) и т.д. Но, надеюсь, это дает вам представление о том, куда идти.

Это также не единственный способ разобрать этот тип строки, но это довольно просто, и не должно быть слишком медленным, хотя на большой входной строке это не будет очень эффективно с точки зрения памяти.

0

Проверьте эту скрипку here.

public class MyObject 
{ 
    public int r {get;set;} 
    public int l {get;set;} 
    public int t {get;set;} 
    public int b {get;set;} 

    public MyObject() 
    { 
    } 

    public void ParseFromString(string val) 
    { 
     string[] splitVal = val.Split(';');  
     int intVal ; 
     if(!int.TryParse(splitVal[0].Replace("l=","").Trim(), out intVal)) 
      intVal = 0; 
     this.l = intVal; 

     if(!int.TryParse(splitVal[1].Replace("r=","").Trim(), out intVal)) 
      intVal = 0; 
     this.r = intVal; 

     if(!int.TryParse(splitVal[2].Replace("t=","").Trim(), out intVal)) 
      intVal = 0; 
     this.t = intVal; 

     if(!int.TryParse(splitVal[3].Replace("b=","").Trim(), out intVal)) 
      intVal = 0; 
     this.b = intVal;    
    } 

    public string ParseToString() 
    { 
     return "l=" + this.l + "; r=" + this.r + "; t=" + this.t + "; b=" + this.b + ""; 
    } 
} 
0

Я думаю, что лучший подход был бы использовать регулярное выражение в данном случае:

var position = "l=50; r=190; t=-430; b=-480"; 
var match = Regex.Match(position, @"l=(-?\d+); r=(-?\d+); t=(-?\d+); b=(-?\d+)"); 
if (!match.Success) 
    throw new Exception("invalid data"); 

var l = Convert.ToInt32(match.Groups[1].Value); 
var r = Convert.ToInt32(match.Groups[2].Value); 
var t = Convert.ToInt32(match.Groups[3].Value); 
var b = Convert.ToInt32(match.Groups[4].Value); 

// modify the values as you like, for example: t -= 75; b -=75; 

var newPosition = $"l={l}; r={r}; t={t}; b={b}"; 
0

Вы можете создать структуру Позиции, как это:

public struct Position 
{ 
    public int Left { get; private set; } 
    public int Top { get; private set; } 
    public int Right { get; private set; } 
    public int Bottom { get; private set; } 

    public Position(int left, int top, int right, int bottom) 
    { 
     Left = left; 
     Top = top; 
     Right = right; 
     Bottom = bottom; 
    } 

    public Position(string positionText) 
    { 
     string pattern = @"(?=l=(?<left>[\d\-]+))|(?=t=(?<top>[\d\-]+))|(?=r=(?<right>[\d\-]+))|(?=b=(?<bottom>[\d\-]+))"; 
     Match match = Regex.Match(positionText, pattern); 
     int left = Convert.ToInt32(match.Groups["left"].Value); 
     int top = Convert.ToInt32(match.Groups["top"].Value); 
     int right = Convert.ToInt32(match.Groups["right"].Value); 
     int bottom = Convert.ToInt32(match.Groups["bottom"].Value); 
     Left = left; 
     Top = top; 
     Right = right; 
     Bottom = bottom; 
    } 

    public Position Move(int leftDelta = 0, int topDelta=0, int rightDelta=0, int bottomDelta = 0) 
    { 
     return new Position(Left + leftDelta, Top + topDelta, Right + rightDelta, Bottom + bottomDelta); 
    } 

    public override string ToString() 
    { 
     return string.Format("l={0}; r={1}; t={2}; b={3}", Left, Right, Top, Bottom); 
    } 
} 

Затем вы можете использовать это примерно так:

Position oldPosition = new Position("l=50; r=190; t=-430; b=-480"); 
Position newPosition = oldPosition.Move(topDelta: -75, bottomDelta: -75); 
string newPositionText = newPosition.ToString(); 
+0

Почему вы выполняете 'Regex.Match' четыре отдельных раза? Это невероятно неэффективно. –

+0

Это должно было дать параметры в любом порядке, но позитивный взгляд был бы лучше. Исправлена – krimog

0

Я думаю, что простой метод может сделать трюк:

public static string ModifyPositions(string positionsInput, int displacement) 
    { 
     string input = "l=50; r=190; t=-430; b=-480"; 
     var pattern = @"(t|b)=(-?\d+)"; 
     var regex = new Regex(pattern); 
     var matches = regex.Matches(input); 
     foreach (Match match in matches) 
     { 
      input = input.Replace(match.Groups[2].Value, (int.Parse(match.Groups[2].Value) + displacement).ToString()); 
     } 

     return input; 
    } 

В вашем случае смещения -75, positionsInput является «л = 50; г = 190; т = -430; b = -480 "

Смежные вопросы