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.