Bir nesne dizisindeki bir özniteliğin maksimum değerini bulma


413

Aşağıdaki JSON dilim max "y" değeri elde etmek için gerçekten hızlı, temiz ve verimli bir yol arıyorum:

[
  {
    "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
  }
]

Bir for-loop, bunun için tek yol mu? Bir şekilde kullanmaya hevesliyim Math.max.


4
Yalnızca bulunan min attr değerini değil, nesneyi nasıl döndürürdünüz?
Mike Lyons

1
Kendi yararım için bu konuda bazı hızlı mükemmel testler yaptım. jsperf.com/finding-the-max-value-an-array-of-objects
Andy Polhill

Yanıtlar:


739

İçindeki ynesnelerin maksimum değerini bulmak için array:

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

47
Maksimum değerin bulunduğu nesnenin nasıl döndürüleceğini göstermek için bu cevabı genişletebilir misiniz? Bu çok yardımcı olur, teşekkürler!
Mike Lyons

19
İşte keman! umarım bu birine yardım eder jsfiddle.net/45c5r246
mili

24
@MikeLyons hala asıl nesneyi almayı önemsiyorsanız: jsfiddle.net/45c5r246/34
tobyodavies

11
Lütfen cevabınızı açıklayın!
John William Domingo

12
FWIW benim anlayış, bir işlev için Apply çağırmak işlev için belirtilen bir değer thisve dizi olarak belirtilen bir dizi bağımsız değişken ile işlev yürüttüğünüz zaman olduğunu . İşin püf noktası, uygulamanın diziyi bir dizi gerçek işlev bağımsız değişkenine dönüştürmesidir. Yani bu durumda nihayet idam edilen fonksiyon Math.max(0.0265, 0.0250, 0.024, 0.031)ile çağırır . Açıkçası neden olması gerektiğini anlayamıyorum , işlevin geçerli olmasını gerektirdiğini sanmıyorum . Oh ve işte burada uygun bir açıklama var: stackoverflow.com/questions/21255138/…thisMathMaththis
Daniel C

263

"Y" özelliği bir nesne dizisinde en yüksek değere sahip nesneyi bulma

Bir yolu Array azaltmak kullanmak olacaktır ..

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

https://developer.mozilla.org/tr-TR/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce http://caniuse.com/#search=reduce (IE9 ve üstü)

IE'yi (yalnızca Edge) desteklemeniz gerekmiyorsa veya Babel gibi bir ön derleyici kullanabiliyorsanız, daha kısa sözdizimini kullanabilirsiniz.

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

7
Bu iyi bir yanıttır, ancak bir başlangıç ​​değeri iletmek veya veri dizisinin boş olması durumunda bir hata alırsınız. yani nesnelerin bir oto-indeks endeksi için. const max = data.reduce((prev, current) => (prev.y > current.y) ? prev : current, 1)
juliangonzalez

2
İyi bir noktaya değindin, muhtemelen null1'i
seçerdim

25
Bunun, nesneden maksimum değeri değil, maksimum değeri olan nesneyi döndürdüğünü unutmayın. İstediğiniz şey bu olabilir veya olmayabilir. Benim durumumda istediğim buydu. +1
John

1
İyi tamamlayıcı cevap!
Efsaneler

Mükemmel cevap! İlk başta, azalma nedeniyle tereddüt ettim, ama yine de tekrarlamamız gerekecek, neden olmasın?
shapiro yaacov

146

temiz ve basit ES6 (Babel)

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

İkinci parametre arrayToSearchInboşsa varsayılan bir değer sağlamalıdır .


8
Ayrıca 's iyi Döndürdüğü olduğunu bilmek -Infinity, (a truthy boş bir dizi için değer)
icl7126

1
Bu, Babil olmayan çoğu modern tarayıcıda desteklenmektedir.
Eugene Kulabuhov

20
-Infinityboş bir dizi için döndüğü gibi , bir başlangıç ​​değeri iletebilirsinizMath.max(...state.allProjects.map(o => o.id), 1);
juliangonzalez

5
Bu şimdi kabul edilen cevap olmalı ... kesinlikle daha kısa bir yaklaşım.
nickb

1
eksi değerleri için sap harf değişikliği 0için arrayToSearchIn[0].y. Zaman karmaşıklığı karşılaştırması: stackoverflow.com/a/53654364/860099
Kamil Kiełczewski

41

Eksi sayıları işleyen ONELINERS ağacının karşılaştırılması ( adizi girişi ):

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)

burada düzenlenebilir bir örnek . Fikirler: maxA , maxB ve maxC ( maxB'nin yan etkisi, yerinde olduğu için dizinin adeğiştirilmesidir sort).

Daha büyük diziler için Math.max...istisna atar: Maksimum çağrı yığını boyutu aşıldı (Chrome 76.0.3809, Safari 12.1.2, tarih 2019-09-13)


2
Görevi gerçekleştirmek için çok akıllı yöntemler. Nice
TetraDev

Üzgünüz, yanlışlıkla reddedildi ve çok fazla zaman geçtiğinden sorunuzu düzenlemeden geri alınamadı.
Günter Zöchbauer

Teşekkürler harika analiz.
d337

Mevcut seçeneklerin ve yaklaşımlar arasındaki farklılıkların bu dağılımı için teşekkür ederiz.
FistOfFury

Dikkat edilmesi gereken bir şey, B seçeneğinin , sonunda ybırakarak tüm nesneyi maksimum değerle elde etmeyi çok daha kolay hale getirmesidir .y.
FistOfFury

23

İlk olarak, JSON dizesini ayrıştırmalısınız, böylece üyelerine kolayca erişebilirsiniz:

var arr = $.parseJSON(str);

mapDeğerleri ayıklamak için yöntemi kullanın :

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

Sonra diziyi maxyöntemde kullanabilirsiniz:

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

Veya tek astar olarak:

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

15
EtiketlenmemişjQuery
Robin van Baalen

1
@RobinvanBaalen: Evet, haklısın. Ancak JSON ile etiketlendi, ancak kabul edilen cevap bunu görmezden geliyor ve tobyodavies de bu sorunun konusu kaldırıldı ... Belki de soruya jquery eklemeliyim ...;)
Guffa

8
@Tobyodavies'in etiketlendiğini görmezden gelmesi önemli değil - cevabında jsonharici bir javascript kütüphanesi kullanmıyor :)
Robin van Baalen

23

Kabul edilen yanıtı adım adım açıklamak istiyorum :

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>');

Daha fazla bilgi:


Harika bir açıklama! Kod yorumlarında değilse okumak biraz daha kolay olabilir, ama yine de - harika iş
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
Bunun @ AndyPolhill'in cevabından farkı nedir?
Lewis

7

siz (veya burada birisi) lodashyardımcı program kitaplığını kullanmakta özgürseniz , sizin durumunuzda çok kullanışlı olacak bir maxBy işlevine sahiptir.

dolayısıyla şöyle kullanabilirsiniz:

_.maxBy(jsonSlice, 'y');

6

Ya da basit bir tür! Gerçekçi olmak :)

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

Güzel fikir 1 (en kısa kod), ancak küçük hata var - değiştir a.y<a.yiçin b.y-a.y. Zaman karmaşıklığı karşılaştırması burada: stackoverflow.com/a/53654364/860099
Kamil Kiełczewski

2
Maksimum değeri bulmak O (n) 'dir. Bu O (nlogn). Verimlilikten ödün vermediği sürece basit kod yazmak iyidir.
Wildhammer

@Wildhammer - Bir darboğazın optimize edildiğine dair kanıtınız olduğunda aslında Mikro optimizasyon buna değer. . Çoğu durumda, basit kod, yüksek verimli koddan daha iyi bir seçimdir.
Kamil Kiełczewski

@ KamilKiełczewski Bu makaledeki her iki dizi karşılaştırması da fark katsayılarında olduğu gibi aynı karmaşıklığa sahiptir. Örneğin biri çözümü bulmak için n zaman birimi alırken diğeri 7n olur. Zaman karmaşıklığı teorisinde bunların ikisi de O (n) 'dir. Maksimum bulma probleminde bahsettiğimiz şey, O (n) ile O (n logn) karşılaştırmasıdır. Şimdi n'nin 10'u geçmediğini garanti ederseniz, çözümünüzü kullanabilirsiniz, aksi takdirde O (n) algoritması her zaman kazanır ve performans (kullanıcı deneyimi) her zaman geliştirici deneyiminden önce olur (endüstri insanlarına sorun, size bunu söylerler!) .
Wildhammer

@Wildhammer nope - dizinizde n = 10000 eleman olsa bile kullanıcı fark görmeyecektir - HERE . Performans optimizasyonu yalnızca uygulama darboğazı için iyidir (örn. Büyük dizileri işlemeniz gerekir) - ancak çoğu durumda bir performans odağı yanlış yaklaşım ve zaman (= para) israfıdır. Bu iyi bilinen kod yaklaşım hatası - daha fazla bilgi edinin: "mikro-optimizasyon"
Kamil Kiełczewski


2

İşte en kısa çözüm (Bir 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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.