Jak uzyskać unikalne wartości w tablicy


167

Jak uzyskać listę unikatowych wartości w tablicy? Czy zawsze muszę używać drugiej tablicy, czy też jest coś podobnego do hashmap Java w JavaScript?

Mam zamiar używać tylko JavaScript i jQuery . Nie można używać żadnych dodatkowych bibliotek.


2
stackoverflow.com/questions/5381621/… - opisuje dokładnie to, co chcesz, myślę?
SpaceBison

1
czy jesteś otwarty na korzystanie z underscore.jsbiblioteki?
jakee

haszmapa java jest w zasadzie tym samym, co obiekt javascript. składnia to {"klucz": "wartość", "klucz2": "wartość2"}
Ian

Interfejsy API kolekcji JavaScript / TypeScript są okropne w porównaniu do Scali,list.toSet
Jordan Stewart,

Odpowiedzi:


120

Skoro pisałem o tym w komentarzach do odpowiedzi @ Rocket, równie dobrze mogę podać przykład, który nie korzysta z bibliotek. Wymaga to dwóch nowych funkcji prototypowych containsiunique

Array.prototype.contains = function(v) {
  for (var i = 0; i < this.length; i++) {
    if (this[i] === v) return true;
  }
  return false;
};

Array.prototype.unique = function() {
  var arr = [];
  for (var i = 0; i < this.length; i++) {
    if (!arr.contains(this[i])) {
      arr.push(this[i]);
    }
  }
  return arr;
}

var duplicates = [1, 3, 4, 2, 1, 2, 3, 8];
var uniques = duplicates.unique(); // result = [1,3,4,2,8]

console.log(uniques);

Aby uzyskać większą niezawodność, możesz wymienić podkładkę containsMDN indexOfi sprawdzić, czy każdy element indexOfjest równy -1: dokumentacja


1
~a.indexOf(b) === (a.indexOf(b) == -1)
Orwellophile,

1
@Lexynux: to była taka, jeśli dla geeków javascript-nerd odpowiedź, której powinien używać tylko ktoś, kto rozumie, co to znaczy, a być może nawet wtedy. Mówi się, że pisanie if (~a.indexOf(b)) ...jest identyczne z pisaniem dłuższym if (a.indexOf(b) == -1) ....
Orwellophile

4
ma to dużą złożoność czasu wykonywania (najgorszy przypadek: O (n ^ 2))
Rahul Arora

1
jest to naprawdę nieefektywne wdrożenie. sprawdzanie tablicy wyników, aby zobaczyć, czy zawiera już element, jest okropne. lepszym podejściem byłoby albo użycie obiektu, który śledzi liczby, albo jeśli nie chcesz korzystać z pamięci dyskowej, posortuj go najpierw w O (n log n), a następnie do liniowego przeciągnięcia i porównaj elementy obok siebie
Isaiah Lee

1
Czy naprawdę potrzebujemy funkcji „zawiera”?
Animesh Kumar

206

Lub dla tych, którzy szukają jednowierszowego (prostego i funkcjonalnego), kompatybilnego z aktualnymi przeglądarkami :

let a = ["1", "1", "2", "3", "3", "1"];
let unique = a.filter((item, i, ar) => ar.indexOf(item) === i);
console.log(unique);

Aktualizacja 18-04-2017

Wygląda na to, że „Array.prototype.includes” jest teraz szeroko obsługiwany w najnowszych wersjach głównych przeglądarek ( zgodność )

Aktualizacja 29-07-2015:

Istnieją plany, aby przeglądarki obsługiwały znormalizowaną metodę „Array.prototype.includes”, która chociaż nie odpowiada bezpośrednio na to pytanie; jest często powiązany.

Stosowanie:

["1", "1", "2", "3", "3", "1"].includes("2");     // true

Pollyfill ( obsługa przeglądarek , źródło z Mozilli ):

// https://tc39.github.io/ecma262/#sec-array.prototype.includes
if (!Array.prototype.includes) {
  Object.defineProperty(Array.prototype, 'includes', {
    value: function(searchElement, fromIndex) {

      // 1. Let O be ? ToObject(this value).
      if (this == null) {
        throw new TypeError('"this" is null or not defined');
      }

      var o = Object(this);

      // 2. Let len be ? ToLength(? Get(O, "length")).
      var len = o.length >>> 0;

      // 3. If len is 0, return false.
      if (len === 0) {
        return false;
      }

      // 4. Let n be ? ToInteger(fromIndex).
      //    (If fromIndex is undefined, this step produces the value 0.)
      var n = fromIndex | 0;

      // 5. If n ≥ 0, then
      //  a. Let k be n.
      // 6. Else n < 0,
      //  a. Let k be len + n.
      //  b. If k < 0, let k be 0.
      var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);

      // 7. Repeat, while k < len
      while (k < len) {
        // a. Let elementK be the result of ? Get(O, ! ToString(k)).
        // b. If SameValueZero(searchElement, elementK) is true, return true.
        // c. Increase k by 1.
        // NOTE: === provides the correct "SameValueZero" comparison needed here.
        if (o[k] === searchElement) {
          return true;
        }
        k++;
      }

      // 8. Return false
      return false;
    }
  });
}

To prawie kopiowanie wklejania z kennebec, ale trzeba przyznać, że przekazanie tablicy jako parametru zamiast używania zamknięcia prawdopodobnie poprawi wydajność.

- muszę powiedzieć, że nie połączyłem kropek, po prostu przeskanowałem w poszukiwaniu jednej wkładki, wyglądałem jak duży post, więc przeskoczyłem, poszedłem i znalazłem alternatywne źródło i ponownie opublikowałem, aby inni mogli szybko znaleźć. To powiedziawszy, twoje prawo; prawie tak samo jak kennebec.
Josh Mc,

Świetnie - nie zdawałem sobie sprawy, że filtr wysłany w tablicy jako parametr i nie chciał pracować na zewnętrznym obiekcie. Właśnie tego potrzebuję - moja wersja javascript (starsza wersja xerces) przez jakiś czas nie będzie miała nowych dodatków.
Gerard ONeill

1
@GerardONeill tak, w niektórych sytuacjach jest to bardzo istotne, np. Jeśli jest funkcjonalnie powiązany i chcesz mieć dostęp do tablicy, do której nie przypisano zmiennej takiej jak .map (...). Filter (...)
Josh Mc

@Josh Mc, czy mógłbyś w jakiś sposób użyć „obejmuje” w „unikalnej” metodzie?
vkelman

143

Oto znacznie czystsze rozwiązanie dla ES6, którego nie ma tutaj. Używa Set i operatora spreadu :...

var a = [1, 1, 2];

[... new Set(a)]

Który powraca [1, 2]


1
To takie sprytne!
Josh Mc,

1
Teraz TO jest jednowierszowe!
Mac,

11
W Typescript musisz użyć, Array.from(... new Set(a))ponieważ Set nie może być niejawnie przekonwertowany na typ tablicy. Tylko jedno ostrzeżenie!
Zachscs

4
@Zachscs, podczas próby wystąpił błąd kompilacji. Czy miałeś na myśli właśnie Array.from(new Set(a))? To wydaje się działać.
adam0101

72

One Liner, czysty JavaScript

Ze składnią 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")

wprowadź opis obrazu tutaj

Ze składnią ES5

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

Zgodność z przeglądarkami : IE9 +


4
nie wiem, dlaczego głosowanie odrzucono. Na początku może być trochę niejasne i być może sklasyfikowane jako „sprytne” i nie pragmatyczne w czytaniu, ale jest deklaratywne, nieniszczące i zwięzłe, w przypadku gdy brakuje większości innych odpowiedzi.
Larry,

1
@Larry to zostało odrzucone, ponieważ dokładnie ta sama odpowiedź została udzielona lata wcześniej.
Alex Okrushko

@AlexOkrushko w porządku - przegapiłem tę odpowiedź ze względu na sposób, w jaki została sformatowana
Larry

7
Wszystko jest jednolite, jeśli umieścisz wszystko w jednej linii :-)
Gary McGill

Fajnie byłoby zaostrzyć równość i a.indexOf(x) === izanotować trzy znaki równości.
treejanitor

20

Używając EcmaScript 2016 możesz to zrobić w ten sposób.

 var arr = ["a", "a", "b"];
 var uniqueArray = Array.from(new Set(arr)); // Unique Array ['a', 'b'];

Zestawy są zawsze unikalne i za pomocą Array.from()można przekonwertować zestaw na tablicę. W celach informacyjnych zapoznaj się z dokumentacją.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects /Zestaw


1
Oto odpowiedź, której powinieneś użyć. indexOf()odpowiedzi są straszne, ponieważ są O (N ^ 2). Rozłożone odpowiedzi są poprawne, ale nie będą działać w przypadku dużych tablic. To jest najlepsze podejście.
Timmmm

20

Teraz w ES6 możemy korzystać z nowo wprowadzonej funkcji ES6

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

LUB według składni rozprzestrzeniania tablicy w iterable

let items = [1,1,1,1,3,4,5,2,23,1,4,4,4,2,2,2]; 
let uniqueItems = [...new Set(items)];

Zwróci unikalny wynik.

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

1
Najczystsze rozwiązanie!
Dimitris Filippou

To jest droga do zrobienia w środowisku JS, które obsługuje new Settego typu (np. Nowoczesny Angular / TypeScript)
Don Cheadle

1
Warto zauważyć, że możesz również użyć składni rozszerzania tablicy w iterable, takie jak Set i Map: let items = [1,1,1,1,3,4,5,2,23,1,4,4,4,2,2,2]; let uniqueItems = [...new Set(items)];
jacobedawson

Uwielbiam te odpowiedzi z ES6!
Glen Thompson,

1
Jest to identyczne z odpowiedzią @Adeel Imran. Proszę nie tworzyć odpowiedzi, które są dokładnie takie same, jak istniejące odpowiedzi.
Timmmm

16

Jeśli chcesz pozostawić oryginalną tablicę nienaruszoną,

potrzebujesz drugiej tablicy, aby zawierała unikalne elementy pierwszej

Większość przeglądarek ma Array.prototype.filter:

var unique= array1.filter(function(itm, i){
    return array1.indexOf(itm)== i; 
    // returns true for only the first instance of itm
});


//if you need a 'shim':
Array.prototype.filter= Array.prototype.filter || function(fun, scope){
    var T= this, A= [], i= 0, itm, L= T.length;
    if(typeof fun== 'function'){
        while(i<L){
            if(i in T){
                itm= T[i];
                if(fun.call(scope, itm, i, T)) A[A.length]= itm;
            }
            ++i;
        }
    }
    return A;
}
 Array.prototype.indexOf= Array.prototype.indexOf || function(what, i){
        if(!i || typeof i!= 'number') i= 0;
        var L= this.length;
        while(i<L){
            if(this[i]=== what) return i;
            ++i;
        }
        return -1;
    }

14

W dzisiejszych czasach możesz użyć typu danych Set ES6, aby przekonwertować swoją tablicę na unikalny zestaw. Następnie, jeśli potrzebujesz użyć metod tablicowych, możesz zmienić je z powrotem w Array:

var arr = ["a", "a", "b"];
var uniqueSet = new Set(arr); // {"a", "b"}
var uniqueArr = Array.from(uniqueSet); // ["a", "b"]
//Then continue to use array methods:
uniqueArr.join(", "); // "a, b"

1
Schludnie, fajnie byłoby zobaczyć kilka liczb wydajności, myślę, że konwersja tych zestawów, szczególnie jeśli są one bardzo dynamiczne i duże, może być problemem, jedynym sposobem na sprawdzenie jest przetestowanie :)
Astronauta

2
Jeśli używasz transpilera lub znajdujesz się w środowisku, które go obsługuje, możesz zrobić to samo bardziej zwięźle, jak:var uniqueArr = [...new Set(arr)]; // ["a", "b"]
Stenerson

Hej, @Astronaut, przeprowadziłeś testy wydajności, jak powiedziałeś?
alexventuraio

8

Nie jest natywny w Javascript, ale wiele bibliotek ma tę metodę.

Underscore.js _.uniq(array)( link ) działa całkiem dobrze ( źródło ).


Dziękuję za udostępnienie! Ta funkcja przyjmuje iterator i kontekst wraz z tablicą jako listę argumentów z wersji 1.4.3.
Kunj

6

Używając jQuery, oto unikalna funkcja Array, którą stworzyłem:

Array.prototype.unique = function () {
    var arr = this;
    return $.grep(arr, function (v, i) {
        return $.inArray(v, arr) === i;
    });
}

console.log([1,2,3,1,2,3].unique()); // [1,2,3]

5
jeśli zamierzasz używać jQuery wewnątrz prototypu podstawowego obiektu javascript, czy nie byłoby lepiej napisać funkcję jQuery, taką jak $.uniqueArray(arr)? Osadzanie odniesień do jQuery w Arrayprototypie wydaje się wątpliwe
jackwanders

1
@jackwanders: Co w tym jest takiego wątpliwego? Jeśli masz na stronie jQuery, użyjmy go.
Rocket Hazmat

Po prostu nowa unikalna funkcja, którą napisałeś, jest teraz zależna od jQuery; nie można go przenieść do nowej witryny lub aplikacji bez upewnienia się, że jest tam używany jQuery.
jackwanders

2
o to mi chodziło; jeśli zamierzasz używać jQuery, utwórz samą funkcję częścią jQuery. Gdybym miał rozszerzyć prototyp obiektu rdzenia, trzymałbym się rdzenia javascript, aby zachować możliwość ponownego użycia. Jeśli ktoś inny patrzy na Twój kod, oczywiste $.uniqueArrayjest, że jest on zależny od jQuery; to też Array.prototype.uniquejest mniej oczywiste .
jackwanders

1
@jackwanders: Chyba. Używam tego w moim kodzie, ponieważ zawsze używam jQuery i po prostu lubię rozszerzać prototypes. Ale teraz rozumiem twój punkt widzenia. I tak zostawię to tutaj.
Rocket Hazmat

6

Krótki i słodki roztwór z użyciem drugiej tablicy;

var axes2=[1,4,5,2,3,1,2,3,4,5,1,3,4];

    var distinct_axes2=[];

    for(var i=0;i<axes2.length;i++)
        {
        var str=axes2[i];
        if(distinct_axes2.indexOf(str)==-1)
            {
            distinct_axes2.push(str);
            }
        }
    console.log("distinct_axes2 : "+distinct_axes2); // distinct_axes2 : 1,4,5,2,3

Krótki? i słodkie? Czy spojrzałeś na najlepsze rozwiązania?
Alex Okrushko

5

Szybki, kompaktowy, bez zagnieżdżonych pętli, działa z każdym obiektem, nie tylko łańcuchami i liczbami, pobiera predykat i tylko 5 linii kodu !!

function findUnique(arr, predicate) {
  var found = {};
  arr.forEach(d => {
    found[predicate(d)] = d;
  });
  return Object.keys(found).map(key => found[key]); 
}

Przykład: Aby znaleźć unikalne przedmioty według typu:

var things = [
  { name: 'charm', type: 'quark'},
  { name: 'strange', type: 'quark'},
  { name: 'proton', type: 'boson'},
];

var result = findUnique(things, d => d.type);
//  [
//    { name: 'charm', type: 'quark'},
//    { name: 'proton', type: 'boson'}
//  ] 

Jeśli chcesz, aby znalazł pierwszy unikalny element zamiast ostatniego, dodaj znaleziony.hasOwnPropery () sprawdź tam.


4

Potrzebujesz tylko zwykłego JS, aby znaleźć unikaty za pomocą Array.some i Array.reduce. W składni ES2015 to tylko 62 znaki.

a.reduce((c, v) => b.some(w => w === v) ? c : c.concat(v)), b)

Array.some i Array.reduce są obsługiwane w IE9 + i innych przeglądarkach. Po prostu zmień funkcje grubych strzałek na zwykłe funkcje, aby były obsługiwane w przeglądarkach, które nie obsługują składni ES2015.

var a = [1,2,3];
var b = [4,5,6];
// .reduce can return a subset or superset
var uniques = a.reduce(function(c, v){
    // .some stops on the first time the function returns true                
    return (b.some(function(w){ return w === v; }) ?  
      // if there's a match, return the array "c"
      c :     
      // if there's no match, then add to the end and return the entire array                                        
      c.concat(v)}),                                  
  // the second param in .reduce is the starting variable. This is will be "c" the first time it runs.
  b);                                                 

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects / Array / Reduce


4

Większość powyższych rozwiązań ma dużą złożoność w czasie wykonywania.

Oto rozwiązanie, które wykorzystuje reducei może wykonać zadanie w czasie O (n).

Array.prototype.unique = Array.prototype.unique || function() {
        var arr = [];
	this.reduce(function (hash, num) {
		if(typeof hash[num] === 'undefined') {
			hash[num] = 1; 
			arr.push(num);
		}
		return hash;
	}, {});
	return arr;
}
    
var myArr = [3,1,2,3,3,3];
console.log(myArr.unique()); //[3,1,2];

Uwaga:

To rozwiązanie nie jest uzależnione od redukcji. Pomysł polega na utworzeniu mapy obiektów i umieszczeniu unikatowych w tablicy.


1

Sposób ES6:

const uniq = (arr) => (arr.filter((item, index, arry) => (arry.indexOf(item) === index)));

1

możesz użyć,

let arr1 = [1,2,1,3];
let arr2 = [2,3,4,5,1,2,3];

let arr3 = [...new Set([...arr1,...arr2])];

da Ci niepowtarzalne elementy,

**> ale jest haczyk,

dla tego "1" i 1 i są elementami różnic, **

drugą opcją jest użycie metody filtrującej na tablicy.


1

Możesz wpisać tablicę z duplikatami, a poniższa metoda zwróci tablicę z unikalnymi elementami.

function getUniqueArray(array){
    var uniqueArray = [];
    if (array.length > 0) {
       uniqueArray[0] = array[0];
    }
    for(var i = 0; i < array.length; i++){
        var isExist = false;
        for(var j = 0; j < uniqueArray.length; j++){
            if(array[i] == uniqueArray[j]){
                isExist = true;
                break;
            }
            else{
                isExist = false;
            }
        }
        if(isExist == false){
            uniqueArray[uniqueArray.length] = array[i];
        }
    }
    return uniqueArray;
}

0

Jedynym problemem z dotychczas podanymi rozwiązaniami jest wydajność. Jeśli martwisz się tym (i prawdopodobnie powinieneś), musisz unikać zagnieżdżonych pętli: for * for, filter * indexOf, grep * inArray, wszystkie iterują tablicę wiele razy. Możesz zaimplementować pojedynczą pętlę z rozwiązaniami takimi jak to lub to


0
Array.prototype.unique = function () {
    var dictionary = {};
    var uniqueValues = [];
    for (var i = 0; i < this.length; i++) {
        if (dictionary[this[i]] == undefined){
            dictionary[this[i]] = i;
            uniqueValues.push(this[i]);
        }
    }
    return uniqueValues; 
}

0

Próbowałem tego problemu w czystym JS. Wykonałem następujące kroki: 1. Sortuj podaną tablicę, 2. zapętlaj posortowaną tablicę, 3. Sprawdź poprzednią wartość i następną wartość z wartością bieżącą

// JS
var inpArr = [1, 5, 5, 4, 3, 3, 2, 2, 2,2, 100, 100, -1];

//sort the given array
inpArr.sort(function(a, b){
    return a-b;
});

var finalArr = [];
//loop through the inpArr
for(var i=0; i<inpArr.length; i++){
    //check previous and next value 
  if(inpArr[i-1]!=inpArr[i] && inpArr[i] != inpArr[i+1]){
        finalArr.push(inpArr[i]);
  }
}
console.log(finalArr);

Próbny


0
function findUniques(arr){
  let uniques = []
  arr.forEach(n => {
    if(!uniques.includes(n)){
      uniques.push(n)
    }       
  })
  return uniques
}

let arr = ["3", "3", "4", "4", "4", "5", "7", "9", "b", "d", "e", "f", "h", "q", "r", "t", "t"]

findUniques(arr)
// ["3", "4", "5", "7", "9", "b", "d", "e", "f", "h", "q", "r", "t"]

0

Mając na uwadze, że indexOfzwróci pierwsze wystąpienie elementu, możesz zrobić coś takiego:

Array.prototype.unique = function(){
        var self = this;
        return this.filter(function(elem, index){
            return self.indexOf(elem) === index;
        })
    }


0

Kolejna myśl na to pytanie. Oto, co zrobiłem, aby to osiągnąć przy mniejszej ilości kodu.

var distinctMap = {};
var testArray = ['John', 'John', 'Jason', 'Jason'];
for (var i = 0; i < testArray.length; i++) {
  var value = testArray[i];
  distinctMap[value] = '';
};
var unique_values = Object.keys(distinctMap);

console.log(unique_values);


0

function findUnique(arr) {
  var result = [];
  arr.forEach(function(d) {
    if (result.indexOf(d) === -1)
      result.push(d);
  });
  return result;
}

var unique = findUnique([1, 2, 3, 1, 2, 1, 4]); // [1,2,3,4]
console.log(unique);


0

Oto podejście z konfigurowalną equalsfunkcją, która może być używana zarówno do prymitywów, jak i do obiektów niestandardowych:

Array.prototype.pushUnique = function(element, equalsPredicate = (l, r) => l == r) {
    let res = !this.find(item => equalsPredicate(item, element))
    if(res){
        this.push(element)
    }
    return res
}

stosowanie:

//with custom equals for objects
myArrayWithObjects.pushUnique(myObject, (left, right) => left.id == right.id)

//with default equals for primitives
myArrayWithPrimitives.pushUnique(somePrimitive)

0

Moja odpowiedź używa Array.filteri Array.indexOfmetod, aby uzyskać unikalne wartości

array.filter((value, index, self)=>self.indexOf(value)===index)

Widziałem to podejście na stronie internetowej, ale ich kod jest inny niż tutaj. Uprościłem kod do jednej linii i umieściłem go tutaj, aby ktoś na tym skorzystał

Uwaga: Moje podejście jest podobne lub takie samo, jak to, które opublikował Josh. Zostawiam to tutaj, ponieważ nazwy zmiennych są oczywiste w moim kodzie.


-1

Zastanawiałem się tylko, czy możemy użyć wyszukiwania liniowego, aby wyeliminować duplikaty:

JavaScript:
function getUniqueRadios() {

var x=document.getElementById("QnA");
var ansArray = new Array();
var prev;


for (var i=0;i<x.length;i++)
  {
    // Check for unique radio button group
    if (x.elements[i].type == "radio")
    {
            // For the first element prev will be null, hence push it into array and set the prev var.
            if (prev == null)
            {
                prev = x.elements[i].name;
                ansArray.push(x.elements[i].name);
            } else {
                   // We will only push the next radio element if its not identical to previous.
                   if (prev != x.elements[i].name)
                   {
                       prev = x.elements[i].name;
                       ansArray.push(x.elements[i].name);
                   }
            }
    }

  }

   alert(ansArray);

}

HTML:

<body>

<form name="QnA" action="" method='post' ">

<input type="radio"  name="g1" value="ANSTYPE1"> good </input>
<input type="radio" name="g1" value="ANSTYPE2"> avg </input>

<input type="radio"  name="g2" value="ANSTYPE3"> Type1 </input>
<input type="radio" name="g2" value="ANSTYPE2"> Type2 </input>


<input type="submit" value='SUBMIT' onClick="javascript:getUniqueRadios()"></input>


</form>
</body>

-1

Oto jedyne rozwiązanie problemu:

var seriesValues = [120, 120, 120, 120];
seriesValues = seriesValues.filter((value, index, seriesValues) => (seriesValues.slice(0, index)).indexOf(value) === -1);
console.log(seriesValues);

Skopiuj, wklej to do konsoli przeglądarki i uzyskaj wyniki, yo :-)


-2

Mam wbudowaną funkcję JQuery Unique .

uniqueValues= jQuery.unique( duplicateValues );

Więcej informacji można znaleźć w dokumentacji jquery API.

http://api.jquery.com/jquery.unique/


8
Zwróć uwagę, że działa to tylko na tablicach elementów DOM, a nie na łańcuchach lub liczbach. - cytat z dokumentacji.
mco
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.