Menemukan nilai maksimal atribut dalam array objek


413

Saya mencari cara yang sangat cepat, bersih, dan efisien untuk mendapatkan nilai "y" maksimum dalam slice JSON berikut:

[
  {
    "x": "8/11/2009",
    "y": 0.026572007
  },
  {
    "x": "8/12/2009",
    "y": 0.025057454
  },
  {
    "x": "8/13/2009",
    "y": 0.024530916
  },
  {
    "x": "8/14/2009",
    "y": 0.031004457
  }
]

Apakah for-loop satu-satunya cara untuk melakukannya? Saya tertarik entah bagaimana menggunakan Math.max.


4
Bagaimana Anda mengembalikan objek dan bukan hanya nilai mintrtr yang ditemukan?
Mike Lyons

1
Untuk keuntungan saya sendiri, saya menjalankan beberapa tes perf cepat tentang ini. jsperf.com/finding-the-max-value-an-array-of-objects
Andy Polhill

Jawaban:


741

Untuk menemukan nilai maksimum yobjek di array:

Math.max.apply(Math, array.map(function(o) { return o.y; }))

47
Bisakah Anda memperluas jawaban ini untuk menunjukkan cara mengembalikan objek tempat nilai maks ditemukan? Itu akan sangat membantu, terima kasih!
Mike Lyons

19
Ini biola! harap ini akan membantu seseorang jsfiddle.net/45c5r246
mili

24
@MikeLyons jika Anda masih ingin mendapatkan objek yang sebenarnya: jsfiddle.net/45c5r246/34
tobyodavies

11
Tolong jelaskan jawaban Anda!
John William Domingo

12
FWIW pemahaman saya adalah ketika Anda memanggil berlaku pada fungsi itu menjalankan fungsi dengan nilai yang ditentukan untuk thisdan serangkaian argumen yang ditentukan sebagai array. Kuncinya adalah bahwa berlaku mengubah array menjadi serangkaian argumen fungsi aktual. Jadi dalam hal ini akhirnya panggilan Math.max(0.0265, 0.0250, 0.024, 0.031)dengan thisfungsi yang dijalankan Math. Saya tidak bisa melihat mengapa itu harus Mathterus terang, saya tidak berpikir fungsi ini memerlukan valid this. Oh dan inilah penjelasan yang tepat: stackoverflow.com/questions/21255138/…
Daniel C

263

Temukan objek yang propertinya "Y" memiliki nilai terbesar dalam array objek

Salah satu cara adalah dengan menggunakan pengurangan Array ..

const max = data.reduce(function(prev, current) {
    return (prev.y > current.y) ? prev : current
}) //returns object

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce http://caniuse.com/#search=reduce (IE9 ke atas)

Jika Anda tidak perlu mendukung IE (hanya Edge), atau dapat menggunakan pra-kompiler seperti Babel Anda bisa menggunakan sintaks yang lebih singkat.

const max = data.reduce((prev, current) => (prev.y > current.y) ? prev : current)

7
Ini adalah jawaban yang baik, namun, Anda ingin memberikan nilai awal atau Anda akan mendapatkan kesalahan jika array data kosong. yaitu untuk indeks objek autoincrement. const max = data.reduce((prev, current) => (prev.y > current.y) ? prev : current, 1)
juliangonzalez

2
Anda mendapatkan poin yang bagus, saya mungkin akan memilih nulllebih dari 1.
Andy Polhill

25
Perhatikan bahwa ini mengembalikan objek yang memiliki nilai maks, bukan nilai maks dari objek. Ini mungkin atau mungkin bukan yang Anda inginkan. Dalam kasus saya, itulah yang saya inginkan. +1
John

1
Jawaban komplementer yang bagus!
Legenda

Jawaban yang sangat bagus! Pada awalnya, saya ragu-ragu karena pengurangan itu, tapi bagaimanapun juga kita perlu mengulang, jadi mengapa tidak?
shapiro yaacov

147

ES6 bersih dan sederhana (Babel)

const maxValueOfY = Math.max(...arrayToSearchIn.map(o => o.y), 0);

Parameter kedua harus memastikan nilai default jika arrayToSearchInkosong.


8
juga baik itu untuk mengetahui bahwa ia mengembalikan -Infinity(a truthy nilai) untuk array kosong
icl7126

1
Ini didukung di sebagian besar browser modern tanpa Babel sekarang.
Eugene Kulabuhov

20
saat kembali -Infinityuntuk array kosong, Anda bisa memberikan nilai awal Math.max(...state.allProjects.map(o => o.id), 1);
juliangonzalez

5
Ini harus menjadi jawaban yang diterima sekarang ... pasti pendekatan yang lebih singkat.
julukan

1
untuk menangani case untuk nilai minus berubah 0menjadi arrayToSearchIn[0].y. Perbandingan kompleksitas waktu: stackoverflow.com/a/53654364/860099
Kamil Kiełczewski

42

Perbandingan ONELINER pohon yang menangani case angka minus (input in aarray):

var maxA = a.reduce((a,b)=>a.y>b.y?a:b).y;  // 30 chars time complexity:  O(n)

var maxB = a.sort((a,b)=>b.y-a.y)[0].y;     // 27 chars time complexity:  O(nlogn)

var maxC = Math.max(...a.map(o=>o.y));      // 26 chars time complexity: >O(2n)

contoh yang dapat diedit di sini . Gagasan dari: maxA , maxB dan maxC (efek samping dari maxB adalah array adiubah karena sortada di tempat).

Untuk array yang lebih besar Math.max...pengecualian lemparan akan terlampaui: Ukuran tumpukan panggilan maksimum terlampaui (Chrome 76.0.3809, Safari 12.1.2, tanggal 2019-09-13)


2
Metode yang sangat pintar untuk menyelesaikan tugas. Nice
TetraDev

Maaf, dibatalkan karena kesalahan dan tidak dapat diurungkan tanpa mengedit pertanyaan Anda karena terlalu banyak waktu berlalu.
Günter Zöchbauer

Terima kasih analisis yang bagus.
d337

terima kasih atas uraian opsi yang tersedia dan perbedaan antar pendekatan.
FistOfFury

satu hal yang perlu diperhatikan adalah opsi B membuatnya lebih mudah untuk mendapatkan seluruh objek dengan nilai maksimal ydengan meninggalkan .ydi akhir.
FistOfFury

23

Pertama, Anda harus mengurai string JSON, sehingga Anda dapat dengan mudah mengakses anggota itu:

var arr = $.parseJSON(str);

Gunakan mapmetode untuk mengekstrak nilai:

arr = $.map(arr, function(o){ return o.y; });

Kemudian Anda bisa menggunakan array dalam maxmetode:

var highest = Math.max.apply(this,arr);

Atau sebagai one-liner:

var highest = Math.max.apply(this,$.map($.parseJSON(str), function(o){ return o.y; }));

15
Itu tidak ditandai denganjQuery
Robin van Baalen

1
@RobinvanBaalen: Ya, Anda benar. Namun tagged dengan JSON tetapi jawaban yang diterima mengabaikan itu, dan tobyodavies juga menghapus itu dari subjek pertanyaan ... Mungkin saya harus menambahkan jquery ke pertanyaan ...;)
Guffa

8
Tidak masalah banyak jika @tobyodavies mengabaikan fakta bahwa itu ditandai json- dia tidak menggunakan perpustakaan javascript eksternal dalam jawabannya :)
Robin van Baalen

23

Saya ingin menjelaskan jawaban singkat yang diterima selangkah demi selangkah:

var objects = [{ x: 3 }, { x: 1 }, { x: 2 }];

// array.map lets you extract an array of attribute values
var xValues = objects.map(function(o) { return o.x; });
// es6
xValues = Array.from(objects, o => o.x);

// function.apply lets you expand an array argument as individual arguments
// So the following is equivalent to Math.max(3, 1, 2)
// The first argument is "this" but since Math.max doesn't need it, null is fine
var xMax = Math.max.apply(null, xValues);
// es6
xMax = Math.max(...xValues);

// Finally, to find the object that has the maximum x value (note that result is array):
var maxXObjects = objects.filter(function(o) { return o.x === xMax; });

// Altogether
xMax = Math.max.apply(null, objects.map(function(o) { return o.x; }));
var maxXObject = objects.filter(function(o) { return o.x === xMax; })[0];
// es6
xMax = Math.max(...Array.from(objects, o => o.x));
maxXObject = objects.find(o => o.x === xMax);


document.write('<p>objects: ' + JSON.stringify(objects) + '</p>');
document.write('<p>xValues: ' + JSON.stringify(xValues) + '</p>');
document.write('<p>xMax: ' + JSON.stringify(xMax) + '</p>');
document.write('<p>maxXObjects: ' + JSON.stringify(maxXObjects) + '</p>');
document.write('<p>maxXObject: ' + JSON.stringify(maxXObject) + '</p>');

Informasi lebih lanjut:


Penjelasan hebat! Mungkin sedikit lebih mudah untuk dibaca jika tidak ada dalam kode komentar, tetapi masih - kerja bagus
Martin

12
var data = [
  { 'name': 'Vins', 'age': 27 },
  { 'name': 'Jan', 'age': 38 },
  { 'name': 'Alex', 'age': 80 },
  { 'name': 'Carl', 'age': 25 },
  { 'name': 'Digi', 'age': 40 }
];
var max = data.reduce(function (prev, current) {
   return (prev.age > current.age) ? prev : current
});
//output = {'name': 'Alex', 'age': 80}

2
Bagaimana ini berbeda dari jawaban @ AndyPolhill?
Lewis

7

jika Anda (atau, seseorang di sini) bebas menggunakan lodashperpustakaan utilitas, ia memiliki fungsi maxBy yang akan sangat berguna dalam kasus Anda.

maka Anda dapat menggunakan seperti itu:

_.maxBy(jsonSlice, 'y');

6

Atau semacam sederhana! Menjaga agar tetap nyata :)

array.sort((a,b)=>a.y<b.y)[0].y

Ide bagus +1 (kode terpendek), tetapi ada bug kecil - ubah a.y<a.yke b.y-a.y. Perbandingan kompleksitas waktu di sini: stackoverflow.com/a/53654364/860099
Kamil Kiełczewski

2
Menemukan max adalah O (n). Ini adalah O (nlogn). Menulis kode sederhana itu bagus asalkan efisiensi tidak dikorbankan.
Wildhammer

@Wildhammer - sebenarnya optimasi Mikro layak ketika Anda memiliki bukti bahwa Anda mengoptimalkan kemacetan. . Dalam kebanyakan kasus, kode sederhana adalah pilihan yang lebih baik daripada kode efisien tinggi.
Kamil Kiełczewski

@ KamilKiełczewski Kedua perbandingan array dalam artikel itu memiliki kompleksitas waktu yang sama perbedaannya dalam koefisien mereka. Sebagai contoh, satu membutuhkan n unit waktu untuk menemukan solusi sementara yang lain adalah 7n. Dalam teori kompleksitas waktu, keduanya adalah O (n). Apa yang kita bicarakan dalam masalah menemukan max adalah perbandingan O (n) dengan O (n logn). Sekarang jika Anda dapat menjamin n tidak melebihi 10 maka Anda dapat menggunakan solusi Anda jika O (n) algoritma selalu menjadi pemenang dan kinerja (pengalaman pengguna) selalu sebelum pengalaman pengembang (tanyakan pada orang-orang industri, mereka memberi tahu Anda!) .
Wildhammer

@Wildhammer nggak - bahkan jika array Anda memiliki n = 10.000 elemen pengguna tidak akan melihat perbedaan - bukti DI SINI . Optimalisasi kinerja hanya baik untuk hambatan aplikasi (mis. Anda perlu memproses array besar) - tetapi dalam kebanyakan kasus fokus kinerja adalah pendekatan yang salah dan membuang-buang waktu (= uang). Ini adalah kesalahan pendekatan kode yang terkenal - baca selengkapnya: "optimasi mikro"
Kamil Kiełczewski


2

Inilah solusi terpendek (One Liner) ES6 :

Math.max(...values.map(o => o.y));

1
var max = 0;                
jQuery.map(arr, function (obj) {
  if (obj.attr > max)
    max = obj.attr;
});


1
Here is very simple way to go:

Your DataSet.

let numberArray = [
  {
    "x": "8/11/2009",
    "y": 0.026572007
  },
  {
    "x": "8/12/2009",
    "y": 0.025057454
  },
  {
    "x": "8/13/2009",
    "y": 0.024530916
  },
  {
    "x": "8/14/2009",
    "y": 0.031004457
  }
]

1. First create Array, containing all the value of Y
let result = numberArray.map((y) => y)
console.log(result) >> [0.026572007,0.025057454,0.024530916,0.031004457]

2. let maxValue = Math.max.apply(null, result)
console.log(maxvalue) >> 0.031004457
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.