Заполнение массивов одинаково

#javascript #arrays

#javascript #массивы

Вопрос:

дано 2 массива (с максимальной длиной, скажем, 15):

 var a = [1,2,3];
var b = [5,6,7,8,9,10,11,12];
var data = [13,14,15,16,17,18,19,20,21,22,23,24,25,26];
  

каков был бы наилучший подход к «заполнению» массивов a в b равной степени данными из data массива, чтобы они были одинаковой длины (или как можно ближе к ней), но не превышали максимальной длины?

требуемый результат может выглядеть следующим образом:

 var a = [1,2,3,13,14,15,16,17,18,19,20,21];
var b = [5,6,7,8,9,10,11,12,22,23,24,25,26];
  


моя ситуация более сложная, и я ищу эффективный способ: у меня есть 2 стороны на экране, на каждой стороне могут быть фотографии профиля ppl из FB. если на одной стороне недостаточно фотографий, мне нужно добавить «поддельные» фотографии, чтобы заполнить ее, чтобы обе стороны выглядели более или менее равномерно заполненными фотографиями

Комментарии:

1. (a.length b.length data.length)/2 , а затем цикл. Почему бы не рассказать нам больше о вашей сложной ситуации?

2. @Brad — цикл? какова была бы логика, которая бы решала, куда что идет?

3. Я бы использовал slice вместо цикла

4. @BeNdErR — теперь здесь идет хороший разговор. не могли бы вы подробнее рассказать о том, как будет работать метод slice в этой ситуации?

5. Я бы посчитал, сколько элементов мне нужно добавить к первому, скажем, n , затем разрезал массив данных с индекса 0 до n и вставил значения в массив a, остальные элементы из n 1 в data . длина будет добавлена к массиву b

Ответ №1:

 var a    = [1,2,3];
var b    = [5,6,7,8,9,10,11,12];
var data = [13,14,15,16,17,18,19,20,21,22,23,24,25,26];

for( var i = data.length; i--; ){
  if (a.length > b.length)
      b.push(data[i])
  else
      a.push(data[i])
}

console.log(a.length, b.length);
  

Комментарии:

1. это здорово. просто.

Ответ №2:

Вот еще один способ без необходимости перебирать элементы:

 var a = [1,2,3],
    b = [5,6,7,8,9,10,11,12],
    data = [13,14,15,16,17,18,19,20,21,22,23,24,25,26];

var targetLength = (a.length   b.length   data.length)/2,
    aCnt = Math.ceil(targetLength) - a.length,
    bCnt = Math.floor(targetLength) - b.length;

a = a.concat(data.slice(0, aCnt));
b = b.concat(data.slice(aCnt, data.length));

// a is [1, 2, 3, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22]
// b is [5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 25, 26]
  

Комментарии:

1. вы также должны проверить, является ли a.length > b.length или a.length < b.length

2. этот ответ выглядит наиболее многообещающим, но, как я понимаю, OP, targetLength может быть произвольным и data может содержать гораздо больше элементов, чем необходимо..

3. @BeNdErR нет, вы этого не делаете в этом алгоритме.

4. вам не нужно data.length в конце. опуская это, это просто означало бы нарезать массив до конца.

Ответ №3:

Взято из комментария Брэда, я полагаю, вы могли бы сделать что-то вроде этого:

 ab=[];
ab=ab.concat(a,b,data);
del = (a.length   b.length   data.length) / 2;
a = [];
b = [];
for (var i = 0; i < Math.ceil(del); i  ) {
    a.push(ab[i]);
    b.push(ab[Math.ceil(del)   i]);
}
  

Ответ №4:

Алгоритм будет выглядеть так:

1) Определите количество элементов в a

2) Определите количество элементов в b

3) Определите количество элементов в data

4) если элементы в a меньше, чем b , то заполняйте из data , пока оно не станет равным b или наоборот

5) если в обоих a и b элементы равны, и data все еще имеют элементы, тогда альтернативно заполните массив a и b .

Ответ №5:

вы хотите, чтобы к последнему индексу a и b относилось 12, а длина конечного массива равна 12!!! я думаю, что вы можете использовать этот алгоритм! :

 for j in data:
  while ( j-max(a)) == 12 ):
   x  
for i in range(x):
 data[i]=a[i]
  

и после этого удалите индексы с номером индекса больше 12!

Ответ №6:

мое решение было таким:

 var a    = [1,2,3];
var b    = [5,6,7,8,9,10,11,12];
var data = [13,14,15,16,17,18,19,20,21,22,23,24,25,26];

var howManyToFill = (data.length   (b.length   a.length)/2)/2;
// take half of the "data" and put it in "a"
a = a.concat(data.slice(0,howManyToFill));
// what's left goes to "b"
b = b.concat(data.slice(howManyToFill));

console.log(a);
console.log(b);
  

Комментарии:

1. Дополнительное объединение и сращивание являются дорогостоящими операциями. Не уверен, что производительность была проблемой, но ваше решение на 80% медленнее, чем то, которое я опубликовал (см. jsperf.com/splitting-arrays ).

2. вы правы. Я избавлюсь от первого конката, в этом нет необходимости

3. ответ был обновлен, чтобы использовать slice его быстрее, чем splice

4. Так почему же вы просто не приняли мой ответ как правильный, поскольку он в основном идентичен тому, что у вас получилось? Вот как работает StackOverflow — задайте вопрос, получите помощь, примите тот, который подходит вам.

5. @Bill — Мне не нужно сразу принимать какой-либо ответ, я ждал больше ответов. в лучшем случае я не принял ваш ответ, потому что ответ Индры, на мой взгляд, был лучше. это читабельно, что является самым важным, и оно является производительным. разве вы не согласны?

Ответ №7:

 var b = [1,2,3];
var a = [5,6,7,8,9,10,11,12];
var data = [13,14,15,16,17,18,19,20,21,22,23,24,25,26];

// find how many more elements need to be added to the smaller array 
var diff = Math.abs(b.length - a.length);

// get the elements to add to the smallest array
var data1 = data.splice(0, diff   ((data.length - diff) / 2));

// data now only contains the elements that will not be added to the smallest array

if (a.length < b.length) {
    // a is the smallest array
    a.push.apply(a,  data1);
    b.push.apply(b, data);
} else {
    // b is the smallest array
    b.push.apply(b,  data1);
    a.push.apply(a, data);
}
  

Комментарии:

1. разве вы не согласны с тем, что этот метод намного сложнее, чем другие ответы здесь?