オブジェクトのプロパティ間で最小/最大値を取得する高速な方法


93

私は次のようなJavaScriptのオブジェクトを持っています:

{ "a":4, "b":0.5 , "c":0.35, "d":5 }

すべてをループすることなく、プロパティの最小値と最大値を取得する高速な方法はありますか?私が持っているオブジェクトは巨大で、2秒ごとに最小/最大値を取得する必要があるためです。(オブジェクトの値は変化し続けます)。


3
@Oleg:ええと、これだけを考えると、JSONである可能性が非常に高いです。Youssef:JSONをオブジェクトに解析し、そのプロパティを繰り返し処理します。
Felix Kling 2012年

@ OlegV.Volkov私はJSON.parse()を使用していますが、それでJsonになるべきではありませんか?
Youssef 2012年

@Youssef解析前はJSON(文字列値)でした。解析後のオブジェクト値です。
–ŠimeVidas 2012

2
JSONはオブジェクトの文字列表記です。JSONをオブジェクトに解析すると、JSON形式ではなくなります
altschuler 2012年

1
コメントがあなたが意図したものであることを確認するので、私はあなたの質問でJSON->オブジェクトを修正する自由を取りました。
Oleg V. Volkov 2012年

回答:


19

n個の要素すべてをループしないと、一般的なケースで最大値/最小値を見つける方法はありません(1からn-1に移動する場合、要素nがより大きく(または小さく)ないかどうかをどのように知ることができますか?現在の最大/最小)?

値は数秒ごとに変わるとおっしゃいました。どの値が変更されるかが正確にわかっている場合は、以前の最大/最小値から始めて、新しい値とのみ比較できますが、この場合でも、変更された値の1つが古い最大/最小であった場合はそれらを再度ループする必要があります。

もう1つの方法は、変更する値の数が少ない場合にのみ、ツリーやヒープなどの構造に値を格納し、新しい値が到着したら適切に挿入(または更新)することです。しかし、それができるかどうかは、あなたの質問に基づいて明確ではありません。

すべての要素をループしながら、特定のリストの最大/最小要素を取得したい場合は、以下のスニペットのようなものを使用できますが、すべてを実行しないとそれを行うことはできません。

var list = { "a":4, "b":0.5 , "c":0.35, "d":5 };
var keys = Object.keys(list);
var min = list[keys[0]]; // ignoring case of empty list for conciseness
var max = list[keys[0]];
var i;

for (i = 1; i < keys.length; i++) {
    var value = list[keys[i]];
    if (value < min) min = value;
    if (value > max) max = value;
}

2
これは、オブジェクトのプロパティの最小値/最大値を取得する方法については説明していません。
fistOfFury

リストではなく、オブジェクトを反復処理しています。minmaxは未定義です。for in代わりにループを使用するつもりでしたか?
tonix

1
@tonixに感謝し、修正しました。
carlosfigueira

138

更新:最新バージョン(ES6 +)

let obj = { a: 4, b: 0.5 , c: 0.35, d: 5 };

let arr = Object.values(obj);
let min = Math.min(...arr);
let max = Math.max(...arr);

console.log( `Min value: ${min}, max value: ${max}` );


元の回答:

これを試して:

let obj = { a: 4, b: 0.5 , c: 0.35, d: 5 };
var arr = Object.keys( obj ).map(function ( key ) { return obj[key]; });

その後:

var min = Math.min.apply( null, arr );
var max = Math.max.apply( null, arr );

ライブデモ: http //jsfiddle.net/7GCu7/1/


21
できることmax = Object.keys(obj).reduce(function(m, k){ return obj[k] > m ? obj[k] : m }, -Infinity);
levi 2014

4
今すぐこれを行うこともできます: Math.max(...arr);
cmac 2017

1
@ cmacES6バージョンを追加しました。
–ŠimeVidas 2017

@ŠimeVidas-Math.min&max関数の3つのドットは何を表していますか?ありがとう
AME 2017年


12

minそして、max、とにかく入力配列をループする必要があります-どのように他彼らは最大または最小の要素を見つけるだろうか?

したがって、クイックfor..inループだけで問題なく動作します。

var min = Infinity, max = -Infinity, x;
for( x in input) {
    if( input[x] < min) min = input[x];
    if( input[x] > max) max = input[x];
}

1
これはIE7 / 8に最適です。Cheers @Niet the Dark Absol
ojhawkins 2013年

minとmaxが配列をループして値を取得することは必ずしも真実ではありません。配列をクイックソートし、その結果に基づいて最小値と最大値を選択する方が現実的です
2015年

7
最速の一種である@goonerifyO(n log n)本質的により遅いである、O(n)ちょうどを通じてスキャンが一度だろうと...
Nietダークアブソル

11

あなたは試すことができます:

const obj = { a: 4, b: 0.5 , c: 0.35, d: 5 };
const max = Math.max.apply(null, Object.values(obj));
console.log(max) // 5

5
// 1. iterate through object values and get them
// 2. sort that array of values ascending or descending and take first, 
//    which is min or max accordingly
let obj = { 'a': 4, 'b': 0.5, 'c': 0.35, 'd': 5 }
let min = Object.values(obj).sort((prev, next) => prev - next)[0] // 0.35
let max = Object.values(obj).sort((prev, next) => next - prev)[0] // 5

1
説明を追加しました。
Andrey Kudriavtsev 2017

4

で試すこともできます Object.values

const points = { Neel: 100, Veer: 89, Shubham: 78, Vikash: 67 };

const vals = Object.values(points);
const max = Math.max(...vals);
const min = Math.min(...vals);
console.log(max);
console.log(min);



3

これは、キーも返すことができ、ループを1つだけ実行できるソリューションです。オブジェクトのエントリを(valで)ソートしてから、最初と最後のエントリを返します。

さらに、既存のオブジェクトを置き換えることができるソート済みオブジェクトを返します。これにより、すでにセミソート済み= O(n)よりも優れているため、将来のソートが高速になります。オブジェクトはES6でも順序を保持することに注意することが重要です。

const maxMinVal = (obj) => {
  const sortedEntriesByVal = Object.entries(obj).sort(([, v1], [, v2]) => v1 - v2);

  return {
    min: sortedEntriesByVal[0],
    max: sortedEntriesByVal[sortedEntriesByVal.length - 1],
    sortedObjByVal: sortedEntriesByVal.reduce((r, [k, v]) => ({ ...r, [k]: v }), {}),
  };
};

const obj = {
  a: 4, b: 0.5, c: 0.35, d: 5
};

console.log(maxMinVal(obj));


ありがとう!値に合わせてキーを保持しながら、最大値を取得する方法を見つけようとしていました。これは役に立ちました!:)
0100111001018

2

異なる深さのネストされた構造の場合、つまり{node: {leaf: 4}, leaf: 1}、これは機能します(lodashまたはアンダースコアを使用):

function getMaxValue(d){
    if(typeof d === "number") {
        return d;
    } else if(typeof d === "object") {
        return _.max(_.map(_.keys(d), function(key) {
            return getMaxValue(d[key]);
        }));
    } else {
        return false;
    }
}

2
var newObj = { a: 4, b: 0.5 , c: 0.35, d: 5 };
var maxValue = Math.max(...Object.values(newObj))
var minValue = Math.min(...Object.values(newObj))

3
古い質問に回答する場合、特にすでに回答が受け入れられている質問の場合に、回答がどのように役立つかを説明するコンテキストを含めると、他のStackOverflowユーザーにとって回答がはるかに役立ちます。参照:良い答えを書くにはどうすればよいですか
デビッドバック

0

これは私のために働きます:

var object = { a: 4, b: 0.5 , c: 0.35, d: 5 };
// Take all value from the object into list
var valueList = $.map(object,function(v){
     return v;
});
var max = valueList.reduce(function(a, b) { return Math.max(a, b); });
var min = valueList.reduce(function(a, b) { return Math.min(a, b); });
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.