Mengira perkara dalam Javascript

WBOY
Lepaskan: 2024-08-08 07:17:32
asal
663 orang telah melayarinya

Counting things in Javascript

Jika anda ingin mengira bilangan item varieti tertentu dalam tatasusunan, anda boleh menapis tatasusunan itu dan menyemak panjang hasilnya.

const letters = ['a','b','b','c','c','c'];
const numberOfC = letters.filter(letter => letter === 'c').length;
console.log(numberOfC); // 3
Salin selepas log masuk

Ini mempunyai kerumitan masa O(n), yang merupakan teori ideal untuk jenis masalah ini. Ia menggunakan beberapa memori tambahan untuk memegang tatasusunan kedua, tetapi untuk mengira hanya satu jenis item, ini adalah pendekatan biasa dan cukup cekap dalam kebanyakan situasi. Walau bagaimanapun, ini bukan pendekatan yang cekap jika anda mahukan pengiraan setiap pelbagai item dalam tatasusunan.

Masalah dengan penapis

Jika kita mahu mengira bukan sahaja 'c' tetapi setiap huruf dalam tatasusunan, aplikasi naif teknik ini akan menjadi seperti ini:

const letters = ['a','b','b','c','c','c'];
letters.forEach((letter, _, arr) => {
   const count = arr.filter(otherLetter => otherLetter === letter).length;
   console.log(letter, count);
});
Salin selepas log masuk

Ini menghasilkan output berikut:

a 1
b 2
b 2
c 3
c 3
c 3
Salin selepas log masuk

Pengiraan adalah betul, tetapi terdapat lebihan, yang boleh diperbaiki dengan menggunakan Set terlebih dahulu.

const letters = ['a','b','b','c','c','c'];
const uniqueLetters = new Set(letters);
for(const letter of uniqueLetters){
   const count = letters.filter(otherLetter => otherLetter === letter).length;
   console.log(letter, count);
};
Salin selepas log masuk

Output yang terhasil tidak mempunyai pendua:

a 1
b 2
c 3
Salin selepas log masuk

Walau bagaimanapun, ia mempunyai kerumitan masa O(n^2), kerana setiap penapis melelang melalui keseluruhan tatasusunan, dan ia mesti melakukannya untuk setiap huruf unik.

Pendekatan yang lebih cekap

Anda boleh melakukan kiraan ini dengan kerumitan masa O(n). Prinsip umum adalah untuk mengulang tatasusunan sekali sahaja. Untuk setiap item yang ditemui, semak sama ada anda sudah mempunyai kiraan untuk item itu. Jika anda berbuat demikian, tambahkannya sebanyak 1. Jika tidak, tambahkan kiraan untuk item itu dengan nilai yang ditetapkan kepada 1.

Javascript mempunyai dua mekanisme berbeza yang sesuai untuk menyimpan kiraan. Kita boleh menggunakan objek atau Peta. Ambil perhatian bahawa ini adalah rujukan kepada struktur data Peta dan bukan kaedah tatasusunan map(). Menggunakan Peta adalah lebih cekap, tetapi menggunakan objek untuk ini masih agak biasa, jadi kita akan melihat cara mengira dengan kedua-duanya.

Mengira dengan Peta

const letters = ['a','b','b','c','c','c'];
const counts = new Map(); // Creates an empty Map
letters.forEach(letter => {
    if(counts.has(letter)) {//Determine if the letter already has a count
        counts.set(letter, counts.get(letter) + 1);//Increment existing count
    }
    else counts.set(letter, 1);//Set new count to 1
});
console.log(counts); //Map(3) { 'a' => 1, 'b' => 2, 'c' => 3 }
Salin selepas log masuk

Has() menyemak sama ada nilai sudah ada dalam Peta. Set() menyimpan nilai dalam Peta, sama ada mencipta nilai baharu atau menimpa nilai sedia ada. Get() memperoleh nilai semasa. Ambil perhatian bahawa has(), set(), dan get() ialah kerumitan masa O(1), kerana cincang digunakan secara dalaman.

Jika kami ingin mengeluarkan kiraan huruf tertentu kemudian, kami boleh melakukan sesuatu seperti:

console.log(counts.get('c'));//3
Salin selepas log masuk

Membilang dengan objek

Walaupun mengira dengan objek adalah lebih perlahan, perbezaan dalam prestasi mungkin tidak ketara jika anda tidak mengira kuantiti item yang banyak. Objek juga mempunyai lebih banyak sokongan pelayar daripada Peta, walaupun perbezaan itu menjadi hampir tidak penting pada ketika ini. Menurut caniuse.com, Map disokong dalam 96.28% pelayar pada masa penulisan ini. Objek adalah bahagian penting dalam bahasa Javascript dan harus mempunyai 100% sokongan penyemak imbas, tetapi caniuse.com tidak mempunyai penyenaraian untuknya. Sebab utama untuk mempelajari cara menggunakan objek untuk kiraan adalah kerana terdapat banyak kod lama yang menggunakan teknik ini. Sesetengah orang yang belajar daripada kod lama juga menulis kod baharu menggunakan pendekatan ini.

const letters = ['a','b','b','c','c','c'];
const counts = {};//Create empty object for holding counts
letters.forEach(letter => {
    if(letter in counts) {//Check if the count exists
        counts[letter]++;//Increment the count
    }
    else counts[letter] = 1;//Set new count to 1
});
console.log(counts);//{ a: 1, b: 2, c: 3 }
Salin selepas log masuk

Kod ini mengikut struktur yang sama seperti kod menggunakan Peta. Perbezaannya adalah dalam sintaks untuk Peta dan objek. Kata kunci "dalam" digunakan untuk menguji sama ada objek mempunyai kunci dengan nama itu. Sintaks kurungan digunakan untuk mendapatkan dan menetapkan nilai. Ambil perhatian bahawa ujian untuk keahlian, tetapan dan mendapatkan nilai daripada objek ialah operasi kerumitan masa O(1), kerana objek secara dalaman menggunakan cincang untuk kekunci.

Masalah mengira objek

Jika perkara yang anda kira adalah objek, penjagaan tambahan diperlukan. Peta mampu menyimpan objek sebagai kunci dan ia mengekalkan jenisnya, tetapi itu menimbulkan masalah untuk perbandingan kesamaan jika anda mempunyai objek yang sama sekali berbeza yang mempunyai semua kunci dan nilai yang sama.

const m = new Map();
m.set({name: "John"}, 5);
console.log(m.has({name: "John"}));//false
Salin selepas log masuk

Kod ini mengeluarkan "false", kerana kedua-dua objek tidak mempunyai kesamaan rujukan. Kedua-dua objek adalah sama dalam kekunci dan nilai, tetapi ia bukan objek yang sama.

const m = new Map();
const obj = {name: "John"}
m.set(obj, 5);
console.log(m.has(obj));//true
Salin selepas log masuk

Versi kod ini mengeluarkan "true", kerana set nilai adalah objek yang sama yang sedang diuji untuk keahlian.

Hasil percubaan mengira objek dengan Peta dalam kebanyakan kes ialah semua objek akan berakhir dengan kiraan 1, kerana setiap has() mengembalikan palsu.

Menggunakan objek untuk mengira objek mempunyai masalah yang berkaitan tetapi berbeza sedikit. Kekunci objek secara automatik dipaksa kepada rentetan (Kecuali apabila ia adalah simbol). Jika anda cuba menggunakan objek sebagai kunci objek lain, paksaan jenis itu mencipta kunci yang sama dengan "[objek Objek]".

const obj = {name: "John"}
const count = {};
count[obj] = 5;
console.log(count);// { '[object Object]': 5 }
Salin selepas log masuk

The result of trying to count objects using objects is you will end up with an object that has "[object Object]" as the key, and the value will be the total number of all the things that were counted. There won't be any individual counts, because every item is treated as "[object Object]".

How to count objects

It is not common that you would need to count objects. If the need arises, the solution depends on whether or not the objects have a unique property that is guaranteed to be unique. For example, objects that have an id number could be counted by counting the id number occurrences instead of counting occurrences of the whole object.

const employees = [
    {id: 1, name: "John"},
    {id: 1, name: "John"},
    {id: 2, name: "Mary"},
    {id: 2, name: "Mary"},
    {id: 2, name: "Mary"},
]
const counts = new Map();
employees.forEach(employee => {
    if(counts.has(employee.id)) {
        counts.set(employee.id, counts.get(employee.id) + 1);
    }
    else counts.set(employee.id, 1);
});
console.log(counts);//Map(2) { 1 => 2, 2 => 3 }
Salin selepas log masuk

This only gives counts with ids and an extra lookup would be needed to associate the counts with names, but we can fix that with a bit more code:

const countsWithNames = [];
for(const count of counts) {
    const employee = employees.find((employee) => employee.id === count[0]);
    countsWithNames.push({employee, count: count[1]});
}
console.log(countsWithNames);
Salin selepas log masuk

The resulting output is:

[
  { employee: { id: 1, name: 'John' }, count: 2 },
  { employee: { id: 2, name: 'Mary' }, count: 3 }
]
Salin selepas log masuk

If there isn't anything like an id that guarantees uniqueness, the only remaining practical option would be to first convert the object to JSON.

const people = [
    {name: "John Doe", age: 25},
    {name: "John Doe", age: 25},
    {name: "Mary Jane", age: 24},
    {name: "Mary Jane", age: 24},
    {name: "Mary Jane", age: 24}
]
const counts = new Map();
people.forEach(person => {
    const personString = JSON.stringify(person);
    if(counts.has(personString)) {
        counts.set(personString, counts.get(personString) + 1);
    }
    else counts.set(personString, 1);
});
console.log(counts);
Salin selepas log masuk

The resulting output is:

Map(2) {
  '{"name":"John Doe","age":25}' => 2,
  '{"name":"Mary Jane","age":24}' => 3
}
Salin selepas log masuk

Note that there are limitations to this approach. For example, objects with circular references cannot be stringified using JSON.stringify().

Counting non-array items

Both the techniques for counting with Maps and for counting with objects can be used to count anything, as long as you can find a way to iterate through the items. Some types of data can be converted to an array, for example, strings can be split, and keys of objects can be accessed as an array via Object.keys().

There are also some iterables that don't need to be converted into an array. For example, it's possible to iterate through the characters of a string by using an index. The same principle can be used in array-like structures like HTML Collections.

Atas ialah kandungan terperinci Mengira perkara dalam Javascript. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!