Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Сравнить два массива (https://javascript.ru/forum/misc/24735-sravnit-dva-massiva.html)

bohdantheone 12.01.2012 03:39

Сравнить два массива
 
Есть два массива, например:
mas1=[id1, id2, id3];
mas2=[id1, id3, id5];


Подскажите, как их сравнить, чтобы, не взирая на расположение элементов, находились похожие?

Livaanderiamarum 12.01.2012 04:15

Цитата:

Сообщение от bohdantheone (Сообщение 149805)
Есть два массива, например:
mas1=[id1, id2, id3];
mas2=[id1, id3, id5];


Подскажите, как их сравнить, чтобы, не взирая на расположение элементов, находились похожие?

1) размеры массивов могут отличаться?
2) у тя в них только строки будут?
3) строки могут быть одинаковые?
4) что в твоем понимании ПОХОЖИЕ?

Aetae 12.01.2012 04:19

Что в результате то должно получиться? Какие значения?

Livaanderiamarum 12.01.2012 04:20

Цитата:

Сообщение от Aetae (Сообщение 149808)
Что в результате то должно получиться? Какие значения?

true false полагаю))

bohdantheone 12.01.2012 04:25

1) размеры массивов могут отличаться - да
2) у тя в них только строки будут - да
3) строки могут быть одинаковые -да
4) что в твоем понимании ПОХОЖИЕ - id1=id1

bohdantheone 12.01.2012 04:27

Цитата:

true false полагаю))
ага, (итоговый вариант - выбранные сообщения будут удалятся)

bohdantheone 12.01.2012 04:29

вот наброска http://jsfiddle.net/bohdantheone/NQatM/

bohdantheone 12.01.2012 04:34

Цитата:

и еще как они могут быть равны если у них разные длинны?
да согласен, протупил

Livaanderiamarum 12.01.2012 04:41

Цитата:

Сообщение от bohdantheone (Сообщение 149812)


bohdantheone 12.01.2012 04:43

Livaanderiamarum,
мои мысли - мои скакуны

рони 12.01.2012 04:56

bohdantheone,
Вариант...
function duplicat(b, c) {
    for (var d = [], e = {}, f = {}, a = 0; a < b.length; a++) e[b[a]] = !0;
    for (a = 0; a < c.length; a++) f[c[a]] = !0;
    for (var g in e) f[g] && d.push(g);
    return d
};
alert(duplicat([1,7,2,8,5,12,45,67],[3,4,5,1,2]))

Livaanderiamarum 12.01.2012 05:03

Цитата:

Сообщение от рони (Сообщение 149817)
bohdantheone,
Вариант...
function duplicat(b, c) {
    for (var d = [], e = {}, f = {}, a = 0; a < b.length; a++) e[b[a]] = !0;
    for (a = 0; a < c.length; a++) f[c[a]] = !0;
    for (var g in e) f[g] && d.push(g);
    return d
};
alert(duplicat([1,7,2,8,5,12,45,67],[3,4,5,1,2]))

твоя функция не сравнивает 2 массива и не находит равныене взирая на расположение элементов , ты не правильно понял что хотел ОП)

твоя функция даже не выдает результат РАВЕНСТВА или НЕ равенства) она выдает только общие найденные элементы) а это тут вообще не причем)

но код обфуксировал зачетно)))

Livaanderiamarum 12.01.2012 05:05

/**
 * сравнивает 2 массива не учитывая порядок элементов
 * 
 * @param {Array}
 *            Первый массив
 * @param {Array}
 *            Второй массив
 * @return {Boolean}
 */
function test(arr, arr2){
	if(arr.length != arr2.length) return false
	var on = 0;
	for( var i = 0; i < arr.length; i++ ){
		for( var j = 0; j < arr2.length; j++ ){
			if(arr[i] === arr2[j]){
				on++
				break
			}
		}
	}
	return on==arr.length?true:false
}
//сравниваем раз
var arr = [ 'привет', 'зима', "нарядная" ];
var arr2 = [ 'нарядная', 'зима', 'привет' ];
alert(test(arr, arr2))

//сравниваем два
var arr = [ 'СТОЛ', 'зима', "нарядная" ];
var arr2 = [ 'нарядная', 'зима', 'привет' ];
alert(test(arr, arr2))

trikadin 12.01.2012 05:05

Livaanderiamarum, а что она, по-твоему, делает? Если массив не пустой - совпадающие элементы есть)

Livaanderiamarum 12.01.2012 05:13

Цитата:

Сообщение от trikadin (Сообщение 149820)
Livaanderiamarum, а что она, по-твоему, делает? Если массив не пустой - совпадающие элементы есть)

Его функция находит общие элементы) и выдает массив с ними)

А нужно сравнить массивы не взирая на порядок элементов)

его функция определит равны они или нет ТОЛЬКО если не будет ни одного совпадения и выдастся пустой массив), если же будит хоть одно, то что-то да выдастся)) и придется еще потом сравнивать длины массива выданного и того который срванивали)) если длины равны то массивы равны)

trikadin 12.01.2012 05:22

Цитата:

Сообщение от Livaanderiamarum
и придется еще потом сравнивать длины массива выданного и того который срванивали)) если длины равны то массивы равны)

Зачем? Ему это не нужно.

Цитата:

Сообщение от bohdantheone
1) размеры массивов могут отличаться - да


Livaanderiamarum 12.01.2012 05:25

Цитата:

Сообщение от trikadin
Зачем? Ему это не нужно.

Ну как это не нужно)! Не нужно было бы не создавал бы топик с такой просьбой))


Нет, размеры массивов не могут отличаться он же потом написал, иначе как они будут РАВНЫМИ, а соответственно ни не будут ПОХОЖИ друг на друга, при том что "в задании" ему нужно найти похожие массивы)

логика;)

рони 12.01.2012 06:14

Livaanderiamarum,
Сравнение двух массивов не учитывая порядок елементов))) за два прохода
function duplicat(b, c) {
    for (var d = [], e = {},a = 0; a < b.length; a++) e[b[a]]? e[b[a]]++:e[b[a]]=1 ;
    for (a = 0; a < c.length; a++) e[c[a]] && d.push(c[a]) && e[c[a]]--;
    return d.length == b.length && c.length == b.length
};
alert(duplicat([1,1,3,4,5],[5,4,3,1,1]))
alert(duplicat([1,1,3,4,5],[5,4,3,1,7]))

рони 12.01.2012 06:20

P.S. если два массива одинаковой длинны --- отсортировать оба и сравнить элементы по порядку ...:write:

bohdantheone 12.01.2012 11:35

рони,
вроде как все работает, спасибо

Livaanderiamarum 12.01.2012 13:44

Цитата:

Сообщение от рони (Сообщение 149824)
Livaanderiamarum,
Сравнение двух массивов не учитывая порядок елементов))) за два прохода
function duplicat(b, c) {
    for (var d = [], e = {},a = 0; a < b.length; a++) e[b[a]]? e[b[a]]++:e[b[a]]=1 ;
    for (a = 0; a < c.length; a++) e[c[a]] && d.push(c[a]) && e[c[a]]--;
    return d.length == b.length && c.length == b.length
};
alert(duplicat([1,1,3,4,5],[5,4,3,1,1]))
alert(duplicat([1,1,3,4,5],[5,4,3,1,7]))

моя функция оптимальнее раз в 10)) можешь проверить)) у тебя столько ненужных вещей делается)

Gozar 12.01.2012 14:48

А я бы использовал indexOf:
var a = [1,2,3];
var b = [1,4,3];

for (var i=0; i<b.length; i += 1){
    if(a.indexOf(b[i]) != -1){
        alert("Удаляем,"+b[i]);
    }
}


indexOf реализация для массивов и строк можно взять тут

А оптимизировать раньше времени, зло!

Скрипт с легкостью можно переписать чтобы он оставлял нужные или собирал их в отдельный массив.

nerv_ 12.01.2012 16:40

Цитата:

Сообщение от Gozar
А я бы использовал indexOf:

Могу ошибаться, но этот вариант в IE работать не будет.

Pavel M. 12.01.2012 16:50

в библиотеке underscore много функций для работы с массивами http://documentcloud.github.com/underscore/#arrays
может помогут?

рони 12.01.2012 16:56

Цитата:

Сообщение от Livaanderiamarum
моя функция оптимальнее раз в 10)) можешь проверить))

Проверил )))
var a = [],b = [];
for (var i=0; i<1000; i++)  {
 a[i] = i;
 b[i] = i;
}
var time = new Date();
function duplicat(b, c) {
    for (var d = [], e = {},a = 0; a < b.length; a++) e[b[a]]? e[b[a]]++:e[b[a]]=1 ;
    for (a = 0; a < c.length; a++) e[c[a]] && d.push(c[a]) && e[c[a]]--;
    return d.length == b.length && c.length == b.length
};
rez_duplicat = duplicat(a,b);
time_duplicat = new Date((new Date()).getTime()-time.getTime()).getTime();

time = new Date();
function test(arr, arr2){
	if(arr.length != arr2.length) return false
	var on = 0;
	for( var i = 0; i < arr.length; i++ ){
		for( var j = 0; j < arr2.length; j++ ){
			if(arr[i] === arr2[j]){
				on++
				break
			}
		}
	}
	return on==arr.length?true:false
}
rez_test = test(a,b);
time_test = new Date((new Date()).getTime()-time.getTime()).getTime();
alert("duplicat : " + rez_duplicat + " => time : " + time_duplicat + "\n"
 + "test : " + rez_test + " => time : " + time_test);

Livaanderiamarum 12.01.2012 17:01

ну вот(( твоя быстрее.( а как она работает?

trikadin 12.01.2012 17:10

Цитата:

Сообщение от nerv_
Могу ошибаться, но этот вариант в IE работать не будет.

Не ошибаетесь, но дописать indexOf не очень сложно)

рони 12.01.2012 17:12

Livaanderiamarum,
при длине массивов 1000 ваша функция обращаеться к массивам 500 тысяч раз моя всего 2 тысячи в этом и выигрыш по времени

Livaanderiamarum 12.01.2012 18:06

Цитата:

Сообщение от рони (Сообщение 149888)
Livaanderiamarum,
при длине массивов 1000 ваша функция обращаеться к массивам 500 тысяч раз моя всего 2 тысячи в этом и выигрыш по времени

Я это знаю я делаю полны перебор, я спросил как работает твоя?

melky 12.01.2012 19:15

Цитата:

Сообщение от Livaanderiamarum (Сообщение 149819)
/**
 * сравнивает 2 массива не учитывая порядок элементов
 * 
 * @param {Array}
 *            Первый массив
 * @param {Array}
 *            Второй массив
 * @return {Boolean}
 */
function test(arr, arr2){
	if(arr.length != arr2.length) return false
	var on = 0;
	for( var i = 0; i < arr.length; i++ ){
		for( var j = 0; j < arr2.length; j++ ){
			if(arr[i] === arr2[j]){
				on++
				break
			}
		}
	}
	return on==arr.length?true:false
}
//сравниваем раз
var arr = [ 'привет', 'зима', "нарядная" ];
var arr2 = [ 'нарядная', 'зима', 'привет' ];
alert(test(arr, arr2))

//сравниваем два
var arr = [ 'СТОЛ', 'зима', "нарядная" ];
var arr2 = [ 'нарядная', 'зима', 'привет' ];
alert(test(arr, arr2))

ой. узнаю метод пузырька!ещё в школе на информатике проходил.
но в методе пузырька даже меньше итераций, чем здесь :Р
Цитата:

Сообщение от Livaanderiamarum (Сообщение 149853)
моя функция оптимальнее раз в 10)) можешь проверить)) у тебя столько ненужных вещей делается)

он самый простой и самый медленный из существующих.

рони 12.01.2012 19:18

Livaanderiamarum,
Дока :
function duplicat(b, c) {
    for (var d = [], e = {},a = 0; a < b.length; a++) e[b[a]]? e[b[a]]++:e[b[a]]=1 ;
    // создаём обьект c, где ключами являются значения первого массива
    // e[b[a]]? -> ключ есть ? это на тот случай если значения повторятся в массиве
    // увеличиваем значение ключа на 1
    // иначе если ещё ключа нет с таким значением
    // создаём ключ со значением 1
    for (a = 0; a < c.length; a++) e[c[a]] && d.push(c[a]) && e[c[a]]--;
    //пробегаемся по второму массиву
    // смотрим если значение элемента массива  среди ключей
    // нами созданного обьекта  и его значение ещё не ноль -> e[c[a]]
    // если ключ есть, заносим ключ в промежуточный массив d -> d.push(c[a])
    // значение самого ключа уменьшаем
    return d.length == b.length && c.length == b.length
    // проверяем длину промежуточного массива d c длиной массива b
    // они должны совпадать ->  d.length == b.length
    // плюс  должна совпадать  размерность исходных массивов -> c.length == b.length
    // последнюю проверку можно поставить в начало
};

Ок?

рони 12.01.2012 19:37

Livaanderiamarum,
Итого )))
function duplicat(b, c) {
    if(b.length != c.length) return !1;
    // должна совпадать  размерность исходных массивов -> c.length == b.length
    for (var d = 0, e = {},a = 0; a < b.length; a++) e[b[a]]? e[b[a]]++:e[b[a]]=1 ;
    // создаём обьект e где ключами являются значения первого массива
    // e[b[a]]? -> ключ есть ? это на тот случай если значения повторятся в массиве
    // увеличиваем значение ключа на 1
    // иначе если ещё ключа нет с таким значением
    // создаём ключ со значением 1
    for (a = 0; a < c.length; a++) e[c[a]] && d++ && e[c[a]]--;
    // пробегаемся по второму массиву
    // смотрим если значение элемента массива  среди ключей
    // нами созданного обьекта  и его значение ещё не ноль -> e[c[a]]
    // если ключ есть, увеличиваем счётчик d -> d++
    // значение самого ключа уменьшаем
    return d == b.length;
    // проверяем счётчик d c длиной массива b
    // они должны совпадать ->  d == b.length
    };

melky 12.01.2012 19:54

написано без учёта повторений одинаковых значений в массивах.

function compare(arr1, arr2){
    if(arr1.length !== arr2.length) return false;

    var i = 0, a = {};
    // заносим в хеш значения первого массива.
    while(i in arr1) {
        // если на одинаковых позициях стоят одинаковые элементы, то зачем их проверять дальше?
        if(arr1[i] !== arr2[i])
            a[arr1[i]] = undefined;    
        i += 1;
    }
    // проходимся по элементам второго массива
    // если значения нет в хеше (т.е. нет в первом массиве, то сразу возвращается false
    while(i--) if(!(arr2[i] in a)) return false;
    // массивы похожи
    return true;
};

var a = ['a','b','c'], b = ['a','b','СТУЛ'], c = ['b','c','a'];
alert([compare(a,c), compare(b,c)]);


почему я использовал хеши и in ? на хабре увидел статью про то, что время на проверку существования через in во всех браузерах всегда равно нулю :)
хотя вместо хеша можно было бы использовать массив первый и indexOf... но это не для IE.

Aetae 12.01.2012 20:20

Ваши решения не учитывают маааленький нюанс - массивы могут быть и такими:
[ 1, '2', function b(){}, {c:d} ]

melky 12.01.2012 20:29

Цитата:

Сообщение от Aetae (Сообщение 149954)
Ваши решения не учитывают маааленький нюанс - массивы могут быть и такими:
[ 1, '2', function b(){}, {c:d} ]

условия :
Цитата:

Сообщение от bohdantheone (Сообщение 149810)
1) размеры массивов могут отличаться - да
2) у тя в них только строки будут - да
3) строки могут быть одинаковые -да
4) что в твоем понимании ПОХОЖИЕ - id1=id1


Livaanderiamarum 12.01.2012 20:52

Цитата:

Сообщение от Aetae (Сообщение 149954)
Ваши решения не учитывают маааленький нюанс - массивы могут быть и такими:
[ 1, '2', function b(){}, {c:d} ]

ПО этому я и не использовал метод зансения ЗНАЧЕНИЙ в ИМЕНА свойств обьекта, хотя это была первая мысль. Да и делал функцию не для Опа, а для развлечения скорее.

Livaanderiamarum 12.01.2012 20:55

Цитата:

Сообщение от melky (Сообщение 149935)
я сделал так :

function compare(arr1, arr2){
    if(arr1.length !== arr2.length) return false;

    var i = 0, a = {};
    // заносим в хеш значения первого массива.
    while(i in arr1) {
        a[arr1[i++]] = undefined;    
    }
    // проходимся по элементам второго массива
    // если значения нет в хеше (т.е. нет в первом массиве, то сразу возвращается false
    while(i--) if(!(arr2[i] in a)) return false;
    // массивы похожи
    return true;
};

var a = ['a','b','c'], b = ['a','b','СТУЛ'], c = ['b','c','a'];
alert([compare(a,c), compare(b,c)]);

Метод пузырька )) только в методе пузырька итераций меньше и можно сравнивать НЕ ТОЛЬКО строки))

Livaanderiamarum 12.01.2012 21:08

Напишите ка умельцы наши функцию быстрее чем моя для ПРОСТО СРАВНЕНИЯ двух массивов, при условии что в них лежат примитивные значения) и при условии что массивы раной длинны не равны. иными словами сравнить массивы игнорируя порядок элементов)

Gozar 12.01.2012 21:21

Цитата:

Сообщение от nerv_ (Сообщение 149877)
Могу ошибаться, но этот вариант в IE работать не будет.

Чем тебя не устроила реализация:
Цитата:

indexOf is a recent addition to the ECMA-262 standard
данная по ссылке?

Вопрос ко всем - А где выполняется условие:
Цитата:

Сообщение от bohdantheone (Сообщение 149811)
итоговый вариант - выбранные сообщения будут удалятся

true false насколько я понял вообще не нужны ТС.

melky 12.01.2012 21:30

Цитата:

Сообщение от Livaanderiamarum (Сообщение 149971)
Метод пузырька )) только в методе пузырька итераций меньше и можно сравнивать НЕ ТОЛЬКО строки))

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

ты вообще знаешь этот алгоритм? в чём он заключается и как работает?

Цитата:

Сообщение от Gozar (Сообщение 149981)
true false насколько я понял вообще не нужны ТС.

верно.. но данная тема уже страницу назад переросла из совета в очередное испытание меряние.


Часовой пояс GMT +3, время: 02:40.