javascript - مقارنة - معادلة عدم تكرار الاسماء




الحصول على جميع القيم الفريدة في مصفوفة(إزالة التكرارات) (20)

بطانة واحدة ، جافا سكريبت Pure

مع تركيب ES6

list = list.filter((x, i, a) => a.indexOf(x) == i)

x --> item in array
i --> index of item
a --> array reference, (in this case "list")

مع تركيب ES5

list = list.filter(function (x, i, a) { 
    return a.indexOf(x) == i; 
});

توافق المتصفح : IE9 +

لدي مجموعة من الأرقام التي أحتاجها للتأكد من أنها فريدة من نوعها. لقد عثرت على مقتطف الشفرة أدناه على الإنترنت وتعمل بشكل رائع إلى أن يحتوي الصفيف على صفر فيه. لقد وجدت هذا البرنامج النصي الآخر هنا على SO يبدو شبهه تمامًا ، لكنه لا يفشل.

إذاً ، من أجل مساعدتي في التعلم ، هل يمكن أن يساعدني أحد في تحديد أين يسير الخط الأولي للنموذج؟

Array.prototype.getUnique = function() {
 var o = {}, a = [], i, e;
 for (i = 0; e = this[i]; i++) {o[e] = 1};
 for (e in o) {a.push (e)};
 return a;
}

مزيد من الإجابات عن سؤال مكرر:

سؤال مماثل:


أبسط fastest (في Chrome) للقيام بذلك:

Array.prototype.unique = function() {
    var a = [];
    for (var i=0, l=this.length; i<l; i++)
        if (a.indexOf(this[i]) === -1)
            a.push(this[i]);
    return a;
}

ببساطة يمر كل عنصر في الصفيف ، واختبار إذا كان هذا العنصر موجودًا بالفعل في القائمة ، وإذا لم يكن كذلك ، فانتقل إلى المصفوفة التي يتم إرجاعها.

وفقا ل jsPerf ، هذه الوظيفة هي fastest - لا تتردد في إضافة الخاصة بك على الرغم من.

الإصدار غير الأولي:

function uniques(arr) {
    var a = [];
    for (var i=0, l=arr.length; i<l; i++)
        if (a.indexOf(arr[i]) === -1 && arr[i] !== '')
            a.push(arr[i]);
    return a;
}

فرز

عندما تحتاج أيضًا لفرز المصفوفة ، فإن ما يلي هو الأسرع:

Array.prototype.sortUnique = function() {
    this.sort();
    var last_i;
    for (var i=0;i<this.length;i++)
        if ((last_i = this.lastIndexOf(this[i])) !== i)
            this.splice(i+1, last_i-i);
    return this;
}

أو غير النموذج الأولي:

function sortUnique(arr) {
    arr.sort();
    var last_i;
    for (var i=0;i<arr.length;i++)
        if ((last_i = arr.lastIndexOf(arr[i])) !== i)
            arr.splice(i+1, last_i-i);
    return arr;
}

وهذا أيضًا fastest في معظم المتصفحات غير الكرومية.


أدرك أن هذا السؤال لديه أكثر من 30 إجابة بالفعل. لكني قرأت جميع الإجابات الموجودة أولاً وأجرتها على بحثي الخاص.

لقد قسمت جميع الإجابات على 4 حلول ممكنة:

  1. استخدم ميزة ES6 جديدة: [...new Set( [1, 1, 2] )];
  2. استخدم الكائن { } لمنع التكرارات
  3. استخدام صفيف مساعد [ ]
  4. استخدم filter + indexOf

في ما يلي نماذج للشفرات في الإجابات:

استخدم ميزة ES6 جديدة: [...new Set( [1, 1, 2] )];

function uniqueArray0(array) {
  var result = Array.from(new Set(array));
  return result    
}

استخدم الكائن { } لمنع التكرارات

function uniqueArray1( ar ) {
  var j = {};

  ar.forEach( function(v) {
    j[v+ '::' + typeof v] = v;
  });

  return Object.keys(j).map(function(v){
    return j[v];
  });
} 

استخدام صفيف مساعد [ ]

function uniqueArray2(arr) {
    var a = [];
    for (var i=0, l=arr.length; i<l; i++)
        if (a.indexOf(arr[i]) === -1 && arr[i] !== '')
            a.push(arr[i]);
    return a;
}

استخدم filter + indexOf

function uniqueArray3(a) {
  function onlyUnique(value, index, self) { 
      return self.indexOf(value) === index;
  }

  // usage
  var unique = a.filter( onlyUnique ); // returns ['a', 1, 2, '1']

  return unique;
}

وتساءلت أيهما أسرع. لقد قدمت نموذجًا من ورقة Google لاختبار الوظائف. ملاحظة: لا تتوفر ميزة ECMA 6 في جداول بيانات Google ، لذا لا يمكنني اختبارها.

ها هي نتيجة الاختبارات:

توقعت أن ترى أن الشفرة التي تستخدم الكائن { } ستفوز لأنها تستخدم التجزئة. لذلك يسرني أن الاختبارات أظهرت أفضل النتائج لهذه الخوارزمية في Chrome و IE. بفضلrab للحصول على الرمز .


أقصر حل مع ES6: [...new Set( [1, 1, 2] )];

أو إذا كنت تريد تعديل نموذج Array الأولي (كما في السؤال الأصلي):

Array.prototype.getUnique = function() {
    return [...new Set( [this] )];
};

تم تنفيذ EcmaScript 6 جزئيًا فقط في المتصفحات الحديثة في الوقت الحالي (أغسطس 2015) ، ولكن أصبحت Babel شائعة جدًا لترميز ES6 (وحتى ES7) مرة أخرى إلى ES5. بهذه الطريقة يمكنك كتابة كود ES6 اليوم!

إذا كنت تتساءل ما الذي تعنيه ... فإن ذلك يسمى عامل الانتشار . من MDN : «يسمح معامل الانتشار بتوسيع التعبير في الأماكن التي يتوقع فيها وجود حجج متعددة (للمكالمات الوظيفية) أو عناصر متعددة (للحروف الحرفية للمصفوفة)». ونظرًا لأن المجموعة هي قابلة للتكرار (ويمكن أن يكون لها قيم فريدة فقط) ، فإن عامل الانتشار سيوسع المجموعة لتعبئة الصفيف.

موارد للتعلم ES6:


إذا كنت تستخدم إطار Prototype ، فلا داعي للقيام بـ 'for' loops ، يمكنك استخدام http://www.prototypejs.org/api/array/uniq مثل هذا:

var a = Array.uniq();  

والتي سوف تنتج مجموعة مكررة مع عدم وجود تكرارات. جئت عبر سؤالك بحثا عن طريقة لحساب سجلات مجموعة متميزة حتى بعد

UNIQ ()

إستعملت

بحجم()

وكانت النتيجة بسيطة ملاحظة عذرا إذا أنا misstyped شيء

تحرير: إذا كنت تريد الهروب من السجلات غير المحددة التي قد ترغب في إضافتها

المدمج()

من قبل ، مثل هذا:

var a = Array.compact().uniq();  

العثور على قيم صفيف فريدة في طريقة بسيطة

function arrUnique(a){
  var t = [];
  for(var x = 0; x < a.length; x++){
    if(t.indexOf(a[x]) == -1)t.push(a[x]);
  }
  return t;
}
arrUnique([1,4,2,7,1,5,9,2,4,7,2]) // [1, 4, 2, 7, 5, 9]

بدون توسيع Array.prototype (يُقال أنه ممارسة سيئة) أو باستخدام jquery / الشرطة السفلية ، يمكنك ببساطة filter الصفيف.

بالحفاظ على آخر مرة:

    function arrayLastUnique(array) {
        return array.filter(function (a, b, c) {
            // keeps last occurrence
            return c.indexOf(a, b + 1) < 0;
        });
    },

أو أول مرة:

    function arrayFirstUnique(array) {
        return array.filter(function (a, b, c) {
            // keeps first occurrence
            return c.indexOf(a) === b;
        });
    },

حسنا ، انها فقط جافا سكريبت ECMAScript 5+ ، وهو ما يعني IE9 + فقط ، ولكن من الجيد لتطوير HTML / JS الأصلي (Windows Store App ، Firefox OS ، Sencha ، Phonegap ، Titanium ، ...).


بناءً على إجابات أخرى ، إليك شكل آخر يأخذ علماً اختيارياً لاختيار استراتيجية (حافظ على أول ظهور أو استمر):

بدون توسيع Array.prototype

function unique(arr, keepLast) {
  return arr.filter(function (value, index, array) {
    return keepLast ? array.indexOf(value, index + 1) < 0 : array.indexOf(value) === index;
  });
};

// Usage
unique(['a', 1, 2, '1', 1, 3, 2, 6]); // -> ['a', 1, 2, '1', 3, 6]
unique(['a', 1, 2, '1', 1, 3, 2, 6], true); // -> ['a', '1', 1, 3, 2, 6]

Extending Array.prototype

Array.prototype.unique = function (keepLast) {
  return this.filter(function (value, index, array) {
    return keepLast ? array.indexOf(value, index + 1) < 0 : array.indexOf(value) === index;
  });
};

// Usage
['a', 1, 2, '1', 1, 3, 2, 6].unique(); // -> ['a', 1, 2, '1', 3, 6]
['a', 1, 2, '1', 1, 3, 2, 6].unique(true); // -> ['a', '1', 1, 3, 2, 6]

لست متأكدًا من سبب كتابة غابرييل سيلفيرا الوظيفة بهذه الطريقة ، لكن شكلًا أبسط يعمل بالنسبة لي تمامًا وبدون الاستعارة هو:

Array.prototype.unique = function() {
  return this.filter(function(value, index, array) {
    return array.indexOf(value, index + 1) < 0;
  });
};

أو في CoffeeScript:

Array.prototype.unique = ->
  this.filter( (value, index, array) ->
    array.indexOf(value, index + 1) < 0
  )

لقد وجدت أن تسلسل مفتاح هاش ساعدني في الحصول على هذا العمل للأشياء.

Array.prototype.getUnique = function() {
        var hash = {}, result = [], key; 
        for ( var i = 0, l = this.length; i < l; ++i ) {
            key = JSON.stringify(this[i]);
            if ( !hash.hasOwnProperty(key) ) {
                hash[key] = true;
                result.push(this[i]);
            }
        }
        return result;
    }

لمعالجة المشكلة بطريقة أخرى ، قد يكون من المفيد عدم وجود نسخ مكررة أثناء تحميل الصفيف الخاص بك ، بالطريقة التي ستفعل بها أداة Set object ولكنها غير متوفرة في جميع المتصفحات حتى الآن. إنه يوفر الذاكرة وأكثر كفاءة إذا كنت بحاجة إلى النظر في محتواه عدة مرات.

Array.prototype.add = function (elem) {
   if (this.indexOf(elem) == -1) {
      this.push(elem);
   }
}

عينة:

set = [];
[1,3,4,1,2,1,3,3,4,1].forEach(function(x) { set.add(x); });

يعطيك set = [1,3,4,2]


مع es6 (ويحافظ على النظام):

[...new Set(myArray)];

هذا النموذج الأولي ليس صحيحًا تمامًا ، لأنه إذا كان لدي صفيف مثل: ["1",1,2,3,4,1,"foo"] ["1","2","3","4"] ["1",1,2,3,4,1,"foo"] سيعود ["1","2","3","4"] و "1" هي سلسلة و 1 عدد صحيح؛ هم مختلفون.

هذا هو الحل الصحيح:

Array.prototype.unique = function(a){
    return function(){ return this.filter(a) }
}(function(a,b,c){ return c.indexOf(a,b+1) < 0 });

باستخدام:

var foo;
foo = ["1",1,2,3,4,1,"foo"];
foo.unique();

سوف ينتج أعلاه ["1",2,3,4,1,"foo"] .


هذا سيفي بالغرض.

function getUnique(a) {
  var b = [a[0]], i, j, tmp;
  for (i = 1; i < a.length; i++) {
    tmp = 1;
    for (j = 0; j < b.length; j++) {
      if (a[i] == b[j]) {
        tmp = 0;
        break;
      }
    }
    if (tmp) {
      b.push(a[i]);
    }
  }
  return b;
}

يمكنك أيضًا استخدام sugar.js:

[1,2,2,3,1].unique() // => [1,2,3]

[{id:5, name:"Jay"}, {id:6, name:"Jay"}, {id: 5, name:"Jay"}].unique('id') 
  // => [{id:5, name:"Jay"}, {id:6, name:"Jay"}]

يمكنك أيضًا استخدام underscore.js .

console.log(_.uniq([1, 2, 1, 3, 1, 4]));
<script src="http://underscorejs.org/underscore-min.js"></script>

والتي سوف تعود:

[1, 2, 3, 4]

إجابة محدثة عن ES6 / ES2015 : باستخدام Set ، يكون حل الخط الواحد هو:

var items = [4,5,4,6,3,4,5,2,23,1,4,4,4]
var uniqueItems = Array.from(new Set(items))

الذي يعود

[4, 5, 6, 3, 2, 23, 1]

كما اقترح le_m ، يمكن أيضًا تقصير هذا باستخدام عامل انتشار ، مثل

var uniqueItems = [...new Set(items)]

الأداء فقط! هذا الرمز ربما 10X أسرع من جميع الرموز هنا * يعمل على جميع المتصفحات وأيضا لديه أدنى تأثير الذاكرة .... وأكثر من ذلك

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

var array=[1,2,3,4,5,6,7,8,9,0,1,2,1];

ثم يمكنك محاولة هذا

var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 1];

function toUnique(a, b, c) { //array,placeholder,placeholder
  b = a.length;
  while (c = --b)
    while (c--) a[b] !== a[c] || a.splice(c, 1);
  return a // not needed ;)
}
console.log(toUnique(array));
//[3, 4, 5, 6, 7, 8, 9, 0, 2, 1]

لقد توصلت مع هذه الوظيفة قراءة هذا المقال ...

http://www.shamasis.net/2009/09/fast-algorithm-to-find-unique-items-in-javascript-array/

أنا لا أحب الحلقة. لديها العديد من المعلمات. أنا أحب while-- حلقة. في حين أن أسرع حلقة في جميع المتصفحات باستثناء تلك التي نحبها كثيرًا ... chrome.

على أي حال كتبت الدالة الأولى التي تستخدم في حين. و yep أنها أسرع قليلاً من الدالة الموجودة في article.but لا يكفي. unique2()

الخطوة التالية استخدام شبيبة الحديثة. Object.keys الأخرى باستبدال حلقة أخرى باستخدام Object.keys js1.7 ... أسرع وأقصر قليلاً (في كروم 2x أسرع) ؛). ليس كافي!. unique3() .

في هذه المرحلة كنت أفكر في ما أحتاج حقا في وظيفتي الفريدة. لا أحتاج إلى المصفوفة القديمة ، أريد وظيفة سريعة. لذلك أنا استخدم 2 في حين حلقات + لصق. unique4()

لا جدوى من القول أنني أعجبت.

الكروم: قفزت العمليات المعتادة 150،000 في الثانية إلى 1،800،000 عملية في الثانية.

أي: 80000 op / s مقابل 3،500،000 op / s

ios: 18،000 op / s vs 170،000 op / s

سفاري: 80،000 op / s vs 6،000،000 op / s

الدليل http://jsperf.com/wgu أو أفضل استخدام console.time ... microtime ... أيا كان

unique5() هو فقط لإظهار ما يحدث إذا كنت تريد الاحتفاظ بالمصفوفة القديمة.

لا تستخدم Array.prototype إذا Array.prototype لا تعرف ما تفعله. لقد فعلت الكثير من النسخ والماضي. استخدم Object.defineProperty(Array.prototype,...,writable:false,enumerable:false}) إذا كنت ترغب في إنشاء prototype.example الأصلي: https://.com/a/20463021/2450730

العرض التوضيحي http://jsfiddle.net/46S7g/

ملاحظة: يتم تدمير صفيفك القديم / becomestheunique بعد هذه العملية.

إذا كنت لا تستطيع قراءة الكود أعلاه اسأل ، اقرأ كتاب javascript أو هنا بعض التوضيحات حول الكود المختصر. https://.com/a/21353032/2450730

بعض تستخدم indexOf ... لا ... http://jsperf.com/dgfgghfghfghghgfhgfhfghfhgfh

للصفائف الفارغة

!array.length||toUnique(array); 

Using object keys to make unique array, I have tried following

function uniqueArray( ar ) {
  var j = {};

  ar.forEach( function(v) {
    j[v+ '::' + typeof v] = v;
  });


  return Object.keys(j).map(function(v){
    return j[v];
  });
}   

uniqueArray(["1",1,2,3,4,1,"foo", false, false, null,1]);

Which returns ["1", 1, 2, 3, 4, "foo", false, null]


Array.prototype.getUnique = function() {
    var o = {}, a = []
    for (var i = 0; i < this.length; i++) o[this[i]] = 1
    for (var e in o) a.push(e)
    return a
}




unique