[Javascript] كيفية دمج صفيفين في عناصر جافا سكريبت وإزالة التكرار


Answers

باستخدام Underscore.js أو Lo-Dash ، يمكنك القيام بما يلي:

_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
=> [1, 2, 3, 101, 10]

http://underscorejs.org/#union

http://lodash.com/docs#union

Question

لدي صفحتان JavaScript:

var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];

أريد أن يكون الإخراج:

var array3 = ["Vijendra","Singh","Shakya"];

يجب أن يكون لديك مجموعة الإخراج إزالة الكلمات المتكررة.

كيف أقوم بدمج مصفوفين في JavaScript حتى أحصل على العناصر الفريدة من كل صفيف بنفس الترتيب الذي تم إدخالها به في المصفوفات الأصلية؟




فقط قم بالتخلص من الحلقات المتداخلة (O (n ^ 2)) و .indexOf() (+ O (n)).

function merge(a, b) {
    var hash = {}, i;
    for (i=0; i<a.length; i++) {
        hash[a[i]]=true;
    } 
    for (i=0; i<b.length; i++) {
        hash[b[i]]=true;
    } 
    return Object.keys(hash);
}



يمكنك تحقيق ذلك ببساطة باستخدام Underscore.js's => uniq :

array3 = _.uniq(array1.concat(array2))

console.log(array3)

ستطبع ["فيجيندرا" ، "سينغ" ، "شاكيا"] .




مجرد رمي في بلدي سنتا.

function mergeStringArrays(a, b){
    var hash = {};
    var ret = [];

    for(var i=0; i < a.length; i++){
        var e = a[i];
        if (!hash[e]){
            hash[e] = true;
            ret.push(e);
        }
    }

    for(var i=0; i < b.length; i++){
        var e = b[i];
        if (!hash[e]){
            hash[e] = true;
            ret.push(e);
        }
    }

    return ret;
}

هذه طريقة أستخدمها كثيرًا ، فهي تستخدم كائنًا كجدول hashlookup لإجراء التدقيق المكرر. بافتراض أن التجزئة هي O (1) ، فإن هذا يعمل في O (n) حيث n هو a.length + b.length. بصراحة ليس لدي أي فكرة عن كيفية عمل المتصفح للعلامة التجارية ، ولكنه يؤدي أداءً جيدًا في العديد من نقاط البيانات.




إذا افترضنا أن المصفوفات الأصلية لا تحتاج إلى نسخ من الازدواجية ، فيجب أن يكون ذلك سريعًا إلى حد ما ، مع الاحتفاظ بالترتيب الأصلي ، ولا يعدّل المصفوفات الأصلية ...

function arrayMerge(base, addendum){
    var out = [].concat(base);
    for(var i=0,len=addendum.length;i<len;i++){
        if(base.indexOf(addendum[i])<0){
            out.push(addendum[i]);
        }
    }
    return out;
}

الاستعمال:

var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
var array3 = arrayMerge(array1, array2);

console.log(array3);
//-> [ 'Vijendra', 'Singh', 'Shakya' ]



Another approach for your review with reduce func:

function mergeDistinct(arResult, candidate){
  if (-1 == arResult.indexOf(candidate)) {
    arResult.push(candidate);
  }
  return arResult;
}

var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];

var arMerge = [];
arMerge = array1.reduce(mergeDistinct, arMerge);
arMerge = array2.reduce(mergeDistinct, arMerge);//["Vijendra","Singh","Shakya"];



أسهل طريقة للقيام بذلك إما استخدام concat() لدمج المصفوفات ثم استخدم filter() لإزالة التكرارات أو لاستخدام concat() ثم وضع الصفيف المدمجة داخل Set() .

الطريق الأول:

const firstArray = [1,2, 2];
const secondArray = [3,4];
// now lets merge them
const mergedArray = firstArray.concat(secondArray); // [1,2,2,3,4]
//now use filter to remove dups
const removeDuplicates = mergedArray.filter((elem, index) =>  mergedArray.indexOf(elem) === index); // [1,2,3, 4]

الطريقة الثانية (ولكن مع آثار الأداء على واجهة المستخدم):

const firstArray = [1,2, 2];
const secondArray = [3,4];
// now lets merge them
const mergedArray = firstArray.concat(secondArray); // [1,2,2,3,4]
const removeDuplicates = new Set(mergedArray);



Array.prototype.union = function (other_array) {
/* you can include a test to check whether other_array really is an array */
  other_array.forEach(function(v) { if(this.indexOf(v) === -1) {this.push(v);}}, this);    
}



looks like the accepted answer is the slowest in my tests;

note I am merging 2 arrays of objects by Key

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
<button type='button' onclick='doit()'>do it</button>
<script>
function doit(){
    var items = [];
    var items2 = [];
    var itemskeys = {};
    for(var i = 0; i < 10000; i++){
        items.push({K:i, C:"123"});
        itemskeys[i] = i;
    }

    for(var i = 9000; i < 11000; i++){
        items2.push({K:i, C:"123"});
    }

    console.time('merge');
    var res = items.slice(0);

    //method1();
    method0();
    //method2();

    console.log(res.length);
    console.timeEnd('merge');

    function method0(){
        for(var i = 0; i < items2.length; i++){
            var isok = 1;
            var k = items2[i].K;
            if(itemskeys[k] == null){
                itemskeys[i] = res.length;
                res.push(items2[i]);
            }
        }
    }

    function method1(){
        for(var i = 0; i < items2.length; i++){
            var isok = 1;
            var k = items2[i].K;

            for(var j = 0; j < items.length; j++){
                if(items[j].K == k){
                    isok = 0;
                    break;
                }
            }

            if(isok) res.push(items2[i]);
        }  
    }

    function method2(){
        res = res.concat(items2);
        for(var i = 0; i < res.length; ++i) {
            for(var j = i+1; j < res.length; ++j) {
                if(res[i].K === res[j].K)
                    res.splice(j--, 1);
            }
        }
    }
}
</script>
</body>
</html>



هذا هو حل ECMAScript 6 باستخدام عامل التوسيع ومجموعة الأدوية.

لا يعمل حاليًا إلا مع Firefox ، وربما مع معاينة Internet Explorer الفنية.

ولكن إذا كنت تستخدم Babel ، فيمكنك الحصول عليها الآن.

// Input: [ [1, 2, 3], [101, 2, 1, 10], [2, 1] ]
// Output: [1, 2, 3, 101, 10]
function mergeDedupe(arr)
{
  return [...new Set([].concat(...arr))];
}



في دوجو 1.6+

var unique = []; 
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
var array3 = array1.concat(array2); // Merged both arrays

dojo.forEach(array3, function(item) {
    if (dojo.indexOf(unique, item) > -1) return;
    unique.push(item); 
});

تحديث

انظر رمز العمل.

http://jsfiddle.net/UAxJa/1/




هنا هو اختلاف طفيف في الحلقة. من خلال بعض التحسينات التي تم إدخالها على أحدث إصدار من Chrome ، تعد هذه الطريقة هي الطريقة الأسرع لحل اتحاد الصفيفتين (Chrome 38.0.2111).

jsperf.com/merge-two-arrays-keeping-only-unique-values

var array1 = ["Vijendra", "Singh"];
var array2 = ["Singh", "Shakya"];
var array3 = [];

var arr = array1.concat(array2),
  len = arr.length;

while (len--) {
  var itm = arr[len];
  if (array3.indexOf(itm) === -1) {
    array3.unshift(itm);
  }
}

أثناء التكرار: ~ 589k ops / s
مرشح: ~ 445k العمليات / ثانية
lodash: 308k ops / s
للحلقات: 225 كيلوبت / ثانية

أشار تعليق إلى أن أحد متغيرات الإعداد الخاصة بي كان يتسبب في قيام الحلقة بالانسحاب من الباقي ، لأنه لم يكن من الضروري تهيئة مصفوفة فارغة للكتابة عليها. أوافق على ذلك ، لذا قمت بإعادة كتابة الاختبار حتى في ميدان اللعب ، وقمت بتضمين خيار أسرع.

http://jsperf.com/merge-two-arrays-keeping-only-unique-values/21

var whileLoopAlt = function(array1, array2) {
    var array3 = [];
    var arr = array1.concat(array2);
    var len = arr.length;
    var assoc = {};

    while(len--) {
        var itm = arr[len];

        if(!assoc[itm]) { // Eliminate the indexOf call
            array3.unshift(itm);
            assoc[itm] = true;
        }
    }

    return array3;
};

في هذا الحل البديل ، قمت بدمج حل صفيف .indexOf() واحد للإجابة لإزالة .indexOf() في الحلقة التي كانت تتباطأ الأشياء كثيرًا مع حلقة ثانية ، وتضمنت بعض التحسينات الأخرى التي اقترحها المستخدمون الآخرون في إجاباتهم كذلك.

لا تزال الإجابة الأعلى هنا مع الحلقة المزدوجة على كل قيمة (i-1) أبطأ بشكل ملحوظ. لا يزال لواش يعمل بقوة ، وما زلت أوصي به لأي شخص لا يمانع في إضافة مكتبة إلى مشروعه. بالنسبة لأولئك الذين لا يرغبون في ذلك ، لا يزال حلقي في حينه يمثل إجابة جيدة ، كما أن إجابة المرشح تحتوي على عرض قوي جدًا هنا ، وتغلب على جميع اختباراتي مع أحدث إصدار من Canary Chrome (44.0.2360) اعتبارًا من كتابة هذه السطور.

تحقق من إجابة مايك وجواب دان ستوكر إذا كنت ترغب في زيادة السرعة. هذه هي أسرع النتائج حتى الآن بعد المرور عبر جميع الإجابات القابلة للتطبيق.




//Array.indexOf was introduced in javascript 1.6 (ECMA-262) 
//We need to implement it explicitly for other browsers, 
if (!Array.prototype.indexOf)
{
  Array.prototype.indexOf = function(elt, from)
  {
    var len = this.length >>> 0;

    for (; from < len; from++)
    {
      if (from in this &&
          this[from] === elt)
        return from;
    }
    return -1;
  };
}
//now, on to the problem

var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];

var merged = array1.concat(array2);
var t;
for(i = 0; i < merged.length; i++)
  if((t = merged.indexOf(i + 1, merged[i])) != -1)
  {
    merged.splice(t, 1);
    i--;//in case of multiple occurrences
  }

تنفيذ طريقة indexOf للمتصفحات الأخرى مأخوذة من MDC




باستخدام Set (ECMAScript 2015) ، سيكون الأمر بهذه البساطة:

const array1 = ["Vijendra", "Singh"];
const array2 = ["Singh", "Shakya"];
const array3 = Array.from(new Set(array1.concat(array2)));



Array.prototype.add = function(b){
    var a = this.concat();                // clone current object
    if(!b.push || !b.length) return a;    // if b is not an array, or empty, then return a unchanged
    if(!a.length) return b.concat();      // if original is empty, return b

    // go through all the elements of b
    for(var i = 0; i < b.length; i++){
        // if b's value is not in a, then add it
        if(a.indexOf(b[i]) == -1) a.push(b[i]);
    }
    return a;
}

// Example:
console.log([1,2,3].add([3, 4, 5])); // will output [1, 2, 3, 4, 5]