2015-06-30 3 views
3

У меня есть массив, напримерКак увеличить индекс массива

string[] data = {"1","2","3","5","6","7","4",....goes on) 

Допустим, я хочу сделать следующую операцию; если третий элемент массива данных является 5 затем переместить все вверх указательного одном месте, в основном массив стали бы тогда

{"1","2","3","","5","6","7","4"...} 

и пробел займет 5 место в.

if (data[3] == "5") 
{ 
    // move index forward one spot 
} 
+5

Должен ли быть массив? было бы намного лучше со списком –

+2

«Список », вероятно, будет лучше в этом случае, поскольку он реализует 'Insert' –

+0

, можете ли вы использовать список вместо массива? – DasDas

ответ

7

В то время как это может быть сделано с массивом, то, вероятно, доказать проще использовать некоторые более высокого уровня, как построить List<T>, а затем преобразовать это обратно в массив должен вам это нужно. Если вам не нужен массив, вы можете просто использовать List<T> самостоятельно.

string[] data = {"1","2","3","5","6","7","4"}; 

var list = new List<string>(data); 

for (var i = 0; i < list.Count; i++) 
{ 
    if (list[i] == "5") 
    { 
     list.Insert(i, ""); 
     i++; 
    } 
} 

data = list.ToArray(); 

Вот рабочий пример: https://dotnetfiddle.net/lHzgFH

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

+0

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

+0

@NicoSchertler согласился, это самый простой, но не обязательно самый эффективный. Я не буду вносить в него поправки, так как большинство лучших вариантов рассматриваются в других ответах. Я добавил к этому заметку. –

1

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

Вы должны использовать List<int> (если у вас нет повода для обработки чисел в виде строки?), И вы должны использовать функции List<int>.IndexOf, чтобы найти «5», а List<int>.Insert добавить пробел.

Возможно, вы даже захотите посмотреть на List<Nullable<int>>, так как «blank» может быть представлено нулем.

2

Как другие предложили, использовать List<>, НО ...

// presize, because we know that there are 
// at least data.Length elements! 
// technically the final array will have a size 
// data.Length <= finalSize <= data.Length * 2 
var list = new List<string>(data.Length); 

for (var i = 0; i < data.Length; i++) 
{ 
    if (data[i] == "5") 
    { 
     list.Add(""); 
    } 

    list.Add(data[i]); 
} 

data = list.ToArray(); 

List<>.Insert() является «медленным», потому что вы должны двигаться каждый элемент после вставленного элемента (это O (п) операции) ... Но фокус в том, что вы можете заполнить List<> один элемент в то время, так что без использования List<>.Insert() и только с помощью List<>.Add()

Теперь ... без создания List<>, мы могли бы рассчитать конечный размер массива, :

int count5 = data.Count(x => x == "5"); 

string[] data2 = new string[data.Length + count5]; 

for (int i = 0, j = 0; i < data.Length; i++, j++) 
{ 
    if (data[i] == "5") 
    { 
     data2[j] = ""; 
     j++; 
    } 

    data2[j] = data[i]; 
} 
+0

Если нас беспокоит эффективность, мы не должны указывать начальную емкость 'data.Length + 1'? – clcto

+0

@clcto Может быть более одного «5» ... – xanatos

+0

уверен, но нас беспокоит только тот, что у индекса 3. – clcto

0

Что-то подобное может работать:

https://msdn.microsoft.com/en-us/library/bb300583%28v=vs.110%29.aspx

«Этот элемент является явной реализацией элемента интерфейса. Его можно использовать только тогда, когда экземпляр массива передается в интерфейс IList. »

Я думаю, что вы можете использовать свой массив в интерфейсе IList. Однако я не могу попробовать свой ответ.

1

Linq раствор (ы):

String[] data = { "1", "2", "3", "5", "6", "7", "4" }; 

    // put "" before any item if it equals to "5" 
    var result = data 
    .SelectMany(item => item == "5" ? new String[] {"", item} : new String[] {item}) 
    .ToArray(); 

    // put "" before 3d item if it equals to "5" 
    var result2 = data 
    .SelectMany((item, index) => (item == "5" && index == 3) ? new String[] {"", item} : new String[] {item}) 
    .ToArray(); 
0

Хотя я считаю, что List<T> ответ лучше, если вы не хотите использовать список, это может быть лучшим решением. В качестве примечания, массивы должны быть статической длиной.

string[] data = {"1","2","3","5","6","7","4"}; 
var valueToChangeAt = 3; 
//The above should be parameters, and passed into this as a separate method 

Queue<String> tempHolder = new Queue<String>(); 

for(var i = 0; i < data.Length; i++) { 
    if(i >= valueToChangeAt-1) 
     tempHolder.Enqueue(data[i]); 
} 

string[] newData = new string[data.Length+1]; 

for(var j = 0; j < valueToChangeAt; j++) 
    newData[j] = data[j]; 

newData[valueToChangeAt-1] = ""; 

for(var k = valueToChangeAt; k < newData.Length; k++) 
    newData[k] = tempHolder.Dequeue(); 

//At this point return newData, allowing your stack and old array to be destroyed. 

Я думаю, что это было бы правильное решение, не создавать множество новых объектов, вы можете абстрагировать к способу и использовать Queue так, как это предполагается использовать.

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